@dudousxd/nestjs-agent-core 0.44.1 → 0.45.1

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.
@@ -41,6 +41,7 @@ __export(genui_exports, {
41
41
  isStandardSchema: () => isStandardSchema,
42
42
  jsonStandardSchema: () => jsonStandardSchema,
43
43
  negotiateCatalog: () => negotiateCatalog,
44
+ partialTree: () => partialTree,
44
45
  prepareUiEmission: () => prepareUiEmission,
45
46
  showToolJsonSchema: () => showToolJsonSchema,
46
47
  snapshotComponentPresentation: () => snapshotComponentPresentation,
@@ -50,6 +51,7 @@ __export(genui_exports, {
50
51
  toSnakeCase: () => toSnakeCase,
51
52
  toolNameFor: () => toolNameFor,
52
53
  treeJsonSchema: () => treeJsonSchema,
54
+ treeNodeId: () => treeNodeId,
53
55
  treeToFlatSpec: () => treeToFlatSpec,
54
56
  treeToText: () => treeToText,
55
57
  validatePresentationBatch: () => validatePresentationBatch,
@@ -414,6 +416,7 @@ function defineComponent(definition) {
414
416
  }
415
417
  if (definition.version !== void 0 && (!Number.isSafeInteger(definition.version) || definition.version <= 0)) throw new RangeError("genui: component version must be a positive safe integer");
416
418
  if (definition.fallbackText !== void 0 && typeof definition.fallbackText !== "function") throw new TypeError("genui: fallbackText must be a function");
419
+ if (definition.streaming !== void 0 && definition.streaming !== "partial" && definition.streaming !== "complete") throw new TypeError("genui: streaming must be 'partial' or 'complete'");
417
420
  return definition;
418
421
  }
419
422
  __name(defineComponent, "defineComponent");
@@ -498,6 +501,97 @@ function toolNameFor(component, prefix = "ui__show_") {
498
501
  }
499
502
  __name(toolNameFor, "toolNameFor");
500
503
 
504
+ // src/genui/progressive.ts
505
+ function treeNodeId(parentId, index) {
506
+ return `${parentId}.${index}`;
507
+ }
508
+ __name(treeNodeId, "treeNodeId");
509
+ function isRecord(value) {
510
+ return typeof value === "object" && value !== null && !Array.isArray(value);
511
+ }
512
+ __name(isRecord, "isRecord");
513
+ function partialTree(catalog, input, options = {}) {
514
+ const maxDepth = options.limits?.maxDepth ?? 12;
515
+ const maxNodes = options.limits?.maxNodes ?? 200;
516
+ const fallback = options.streaming ?? "complete";
517
+ let nodes = 0;
518
+ let broken = false;
519
+ const visit = /* @__PURE__ */ __name((value, id, depth) => {
520
+ if (broken) return void 0;
521
+ if (!isRecord(value)) {
522
+ if (value !== void 0) broken = true;
523
+ return void 0;
524
+ }
525
+ const open = input.isOpen(value);
526
+ const type = value.type;
527
+ if (typeof type !== "string" || open && input.pendingMember(value) === "type") {
528
+ if (!open) broken = true;
529
+ return void 0;
530
+ }
531
+ const definition = catalog.get(type);
532
+ nodes += 1;
533
+ if (definition === void 0 || definition.internal === true || nodes > maxNodes || depth > maxDepth) {
534
+ broken = true;
535
+ return void 0;
536
+ }
537
+ const mode = definition.streaming ?? fallback;
538
+ if (mode === "complete") {
539
+ const checked = open ? void 0 : validatePropsSync(definition.props, value.props ?? {}, catalog.validator);
540
+ if (checked === void 0 || !checked.ok) {
541
+ return {
542
+ id,
543
+ type,
544
+ props: {},
545
+ incomplete: true,
546
+ held: true
547
+ };
548
+ }
549
+ const children2 = childrenOf(value, id, depth, definition.children === true);
550
+ return {
551
+ id,
552
+ type,
553
+ props: checked.value,
554
+ ...children2 !== void 0 && children2.length > 0 ? {
555
+ children: children2
556
+ } : {}
557
+ };
558
+ }
559
+ const props = isRecord(value.props) ? value.props : {};
560
+ const children = childrenOf(value, id, depth, definition.children === true);
561
+ return {
562
+ id,
563
+ type,
564
+ props,
565
+ ...children !== void 0 && children.length > 0 ? {
566
+ children
567
+ } : {},
568
+ ...open ? {
569
+ incomplete: true
570
+ } : {}
571
+ };
572
+ }, "visit");
573
+ const childrenOf = /* @__PURE__ */ __name((value, id, depth, takesChildren) => {
574
+ const raw = value.children;
575
+ if (!Array.isArray(raw)) return void 0;
576
+ if (raw.length > 0 && !takesChildren) {
577
+ broken = true;
578
+ return void 0;
579
+ }
580
+ const children = [];
581
+ for (const [index, child] of raw.entries()) {
582
+ const next = visit(child, treeNodeId(id, index), depth + 1);
583
+ if (next !== void 0) children.push(next);
584
+ }
585
+ return children;
586
+ }, "childrenOf");
587
+ const root = visit(input.value, "root", 1);
588
+ if (broken) return null;
589
+ return {
590
+ root: root ?? null
591
+ };
592
+ }
593
+ __name(partialTree, "partialTree");
594
+
501
595
  // src/genui/tree.ts
502
596
  var GENUI_TREE_COMPONENT = "genui:tree";
503
597
  async function validateTree(catalog, tree, limits = {}, phase = "output") {
@@ -630,34 +724,120 @@ async function validateTree(catalog, tree, limits = {}, phase = "output") {
630
724
  };
631
725
  }
632
726
  __name(validateTree, "validateTree");
633
- function treeJsonSchema(catalog) {
727
+ function treeJsonSchema(catalog, options = {}) {
728
+ const components = catalog.modelComponents();
729
+ const names = components.map((component) => component.name);
730
+ if (options.schema === "loose") {
731
+ return {
732
+ type: "object",
733
+ properties: {
734
+ type: {
735
+ type: "string",
736
+ enum: names,
737
+ description: "Component name from the catalog"
738
+ },
739
+ props: {
740
+ type: "object",
741
+ description: "The component's props, as the catalog describes them"
742
+ },
743
+ children: {
744
+ type: "array",
745
+ items: {
746
+ $ref: "#"
747
+ },
748
+ description: "Nested elements, only for components that take children. A literal JSON array, never a JSON-stringified one."
749
+ }
750
+ },
751
+ required: [
752
+ "type",
753
+ "props"
754
+ ]
755
+ };
756
+ }
757
+ const defs = {};
758
+ const childrenSchema = {
759
+ type: "array",
760
+ items: {
761
+ $ref: "#/$defs/node"
762
+ },
763
+ description: "Nested elements. A literal JSON array, never a JSON-stringified one."
764
+ };
765
+ for (const component of components) {
766
+ defs[`props_${component.name}`] = embeddableProps(toJsonSchema(component.props));
767
+ defs[`node_${component.name}`] = {
768
+ type: "object",
769
+ properties: {
770
+ type: {
771
+ type: "string",
772
+ enum: [
773
+ component.name
774
+ ]
775
+ },
776
+ props: {
777
+ $ref: `#/$defs/props_${component.name}`
778
+ },
779
+ ...component.children === true ? {
780
+ children: childrenSchema
781
+ } : {}
782
+ },
783
+ required: [
784
+ "type",
785
+ "props"
786
+ ],
787
+ additionalProperties: false
788
+ };
789
+ }
790
+ defs.node = {
791
+ anyOf: components.map((component) => ({
792
+ $ref: `#/$defs/node_${component.name}`
793
+ }))
794
+ };
634
795
  return {
635
796
  type: "object",
636
797
  properties: {
637
798
  type: {
638
799
  type: "string",
639
- enum: catalog.modelComponents().map((component) => component.name),
640
- description: "Component name from the catalog"
800
+ enum: names,
801
+ description: "Component name from the catalog. A single component (no children) is a valid tree."
641
802
  },
642
803
  props: {
643
- type: "object",
644
- description: "The component's props, as the catalog describes them"
804
+ description: "The component's props: the schema of the component named by `type`",
805
+ anyOf: components.map((component) => ({
806
+ $ref: `#/$defs/props_${component.name}`
807
+ }))
645
808
  },
646
809
  children: {
647
- type: "array",
648
- items: {
649
- $ref: "#"
650
- },
810
+ ...childrenSchema,
651
811
  description: "Nested elements, only for components that take children. A literal JSON array, never a JSON-stringified one."
652
812
  }
653
813
  },
654
814
  required: [
655
815
  "type",
656
816
  "props"
657
- ]
817
+ ],
818
+ additionalProperties: false,
819
+ $defs: defs
658
820
  };
659
821
  }
660
822
  __name(treeJsonSchema, "treeJsonSchema");
823
+ function embeddableProps(schema) {
824
+ if (schema === void 0 || typeof schema !== "object" || schema === null) {
825
+ return {
826
+ type: "object"
827
+ };
828
+ }
829
+ const references = /* @__PURE__ */ __name((value) => {
830
+ if (Array.isArray(value)) return value.some(references);
831
+ if (typeof value !== "object" || value === null) return false;
832
+ return Object.entries(value).some(([key, nested]) => key === "$ref" || key === "$defs" || key === "definitions" || references(nested));
833
+ }, "references");
834
+ if (references(schema)) return {
835
+ type: "object"
836
+ };
837
+ const { $schema: _schema, ...rest } = schema;
838
+ return rest;
839
+ }
840
+ __name(embeddableProps, "embeddableProps");
661
841
  function treeToFlatSpec(root) {
662
842
  const elements = {};
663
843
  let next = 0;
@@ -928,9 +1108,9 @@ __name(prepareUiEmission, "prepareUiEmission");
928
1108
  // src/genui/tools.ts
929
1109
  var GENUI_SHOW_TOOL = "ui__show";
930
1110
  function genuiTools(catalog, options = {}) {
931
- const tools = options.mode === "tree" ? [
1111
+ const tools = options.mode === "per-component" ? flatComponents(catalog).map((component) => componentTool(catalog, component, options)) : [
932
1112
  treeTool(catalog, options)
933
- ] : flatComponents(catalog).map((component) => componentTool(catalog, component, options));
1113
+ ];
934
1114
  if (options.showTool !== void 0 && options.showTool !== false) {
935
1115
  tools.push(showTool(catalog, options));
936
1116
  }
@@ -1041,6 +1221,9 @@ function treeTool(catalog, options) {
1041
1221
  })
1042
1222
  ].join("\n"), "describeFor");
1043
1223
  const dynamic = options.resolveCatalog !== void 0;
1224
+ const treeSchemaOptions = options.treeSchema !== void 0 ? {
1225
+ schema: options.treeSchema
1226
+ } : {};
1044
1227
  const handler = {
1045
1228
  async execute(input, ctx) {
1046
1229
  const resolved = await catalogFor(catalog, options, scopeOf(ctx));
@@ -1049,6 +1232,10 @@ function treeTool(catalog, options) {
1049
1232
  throw new Error(`invalid UI tree: ${formatIssues(result.issues)}`);
1050
1233
  }
1051
1234
  const root = result.value;
1235
+ const single = flatComponent(resolved, root.type);
1236
+ if (root.children === void 0 && single !== void 0) {
1237
+ return push(ctx, root.type, root.props, single.version);
1238
+ }
1052
1239
  return push(ctx, GENUI_TREE_COMPONENT, {
1053
1240
  root
1054
1241
  });
@@ -1059,7 +1246,36 @@ function treeTool(catalog, options) {
1059
1246
  return {
1060
1247
  available: resolved.modelComponents().length > 0,
1061
1248
  description: describeFor(resolved),
1062
- inputSchema: permissiveSchema(treeJsonSchema(resolved))
1249
+ inputSchema: permissiveSchema(treeJsonSchema(resolved, treeSchemaOptions))
1250
+ };
1251
+ };
1252
+ handler.previewInput = async (scope) => {
1253
+ const resolved = negotiateCatalog(await catalogFor(catalog, options, scopeOf(scope)), scope.uiCapabilities);
1254
+ const streaming = options.streaming ?? "complete";
1255
+ if (!resolved.modelComponents().some((each) => (each.streaming ?? streaming) === "partial")) {
1256
+ return void 0;
1257
+ }
1258
+ return {
1259
+ ...options.streamingThrottleMs !== void 0 ? {
1260
+ throttleMs: options.streamingThrottleMs
1261
+ } : {},
1262
+ render(input) {
1263
+ const tree = partialTree(resolved, input, {
1264
+ streaming,
1265
+ ...options.treeLimits !== void 0 ? {
1266
+ limits: options.treeLimits
1267
+ } : {}
1268
+ });
1269
+ if (tree === null) return null;
1270
+ if (tree.root === null) return void 0;
1271
+ return {
1272
+ component: GENUI_TREE_COMPONENT,
1273
+ props: {
1274
+ root: tree.root
1275
+ },
1276
+ version: 1
1277
+ };
1278
+ }
1063
1279
  };
1064
1280
  };
1065
1281
  return {
@@ -1067,7 +1283,7 @@ function treeTool(catalog, options) {
1067
1283
  name,
1068
1284
  kind: "read",
1069
1285
  description: describeFor(catalog),
1070
- inputSchema: dynamic ? permissiveSchema(treeJsonSchema(catalog)) : asyncJsonStandardSchema(treeJsonSchema(catalog), async (value) => {
1286
+ inputSchema: dynamic ? permissiveSchema(treeJsonSchema(catalog, treeSchemaOptions)) : asyncJsonStandardSchema(treeJsonSchema(catalog, treeSchemaOptions), async (value) => {
1071
1287
  const result = await validateTree(catalog, value, options.treeLimits, "input");
1072
1288
  return result.ok ? {
1073
1289
  value: result.value
@@ -1916,6 +2132,7 @@ __name(canonicalJson, "canonicalJson");
1916
2132
  isStandardSchema,
1917
2133
  jsonStandardSchema,
1918
2134
  negotiateCatalog,
2135
+ partialTree,
1919
2136
  prepareUiEmission,
1920
2137
  showToolJsonSchema,
1921
2138
  snapshotComponentPresentation,
@@ -1925,6 +2142,7 @@ __name(canonicalJson, "canonicalJson");
1925
2142
  toSnakeCase,
1926
2143
  toolNameFor,
1927
2144
  treeJsonSchema,
2145
+ treeNodeId,
1928
2146
  treeToFlatSpec,
1929
2147
  treeToText,
1930
2148
  validatePresentationBatch,