@jini-ai/core 0.6.16 → 0.6.17

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @jini-ai/core
2
2
 
3
+ ## 0.6.17
4
+
5
+ ### Patch Changes
6
+
7
+ - Mark required single-call fields in published batched-tool schemas and descriptions while preserving batching and clear missing-input errors.
8
+
3
9
  ## 0.6.16
4
10
 
5
11
  ### Patch Changes
@@ -20,11 +20,11 @@ export declare const BATCH_GUIDANCE_MARKER = " Batch: ";
20
20
  export declare function withoutBatchGuidance({ description }: {
21
21
  description: string;
22
22
  }, _optional?: {}): string;
23
- /** The top-level `required` fields {@link batchDescriptorFor} moved into its `items` description.
23
+ /** The original top-level `required` fields retained by {@link batchDescriptorFor} as schema metadata.
24
24
  * A batch schema declares no top-level `required`, so a discovery signature built from it alone
25
25
  * makes a single call look argument-free and the model sends `{}` — this recovers them.
26
26
  * @returns The moved field names in order; [] for a non-batch schema or a tool that required none.
27
- * @complexity O(n) in the items description length; pure. */
27
+ * @complexity O(r) time and space for r required fields; pure. */
28
28
  export declare function batchItemRequiredFields({ inputSchema }: {
29
29
  inputSchema: unknown;
30
30
  }, _optional?: {}): string[];
@@ -61,15 +61,16 @@ export declare function batchOutcomeFor({ output }: {
61
61
  }, _options?: {}): BatchResult['outcome'] | undefined;
62
62
  /**
63
63
  * The descriptor a batchable tool publishes: its own schema plus an `items` array, its top-level
64
- * `required` list moved into the `items` description (a batch call sets those per item or once at
65
- * the top level through the declared legacy normalization), and batch guidance appended to its description.
64
+ * `required` list retained as metadata and described on required properties (a batch call sets
65
+ * those per item or once at the top level through the declared legacy normalization), and batch
66
+ * guidance appended to its description.
66
67
  *
67
68
  * @param required.descriptor - The tool's registered descriptor.
68
69
  * @param required.tool - Its batch settings.
69
70
  * @returns A new descriptor; the input is not mutated.
70
71
  * @throws {Error} If the tool publishes no object schema, or already has an `items` property
71
72
  * (the batch field would shadow it) — both developer errors caught at composition time.
72
- * @complexity O(p) in the schema's top-level property count.
73
+ * @complexity O(p + r) time and space for p top-level properties and r required fields.
73
74
  */
74
75
  export declare function batchDescriptorFor({ descriptor, tool }: {
75
76
  descriptor: ToolRegistration["descriptor"];
@@ -18,19 +18,18 @@ export function withoutBatchGuidance({ description }, _optional = {}) {
18
18
  }
19
19
  const ITEM_NEEDS = " Each item needs ";
20
20
  const ITEM_NEEDS_END = " (inside each item).";
21
- /** The top-level `required` fields {@link batchDescriptorFor} moved into its `items` description.
21
+ // Keep discovery requirements through descriptor/schema spreads without adding wire-schema keys.
22
+ const BATCH_ITEM_REQUIRED_FIELDS = Symbol('batchItemRequiredFields');
23
+ /** The original top-level `required` fields retained by {@link batchDescriptorFor} as schema metadata.
22
24
  * A batch schema declares no top-level `required`, so a discovery signature built from it alone
23
25
  * makes a single call look argument-free and the model sends `{}` — this recovers them.
24
26
  * @returns The moved field names in order; [] for a non-batch schema or a tool that required none.
25
- * @complexity O(n) in the items description length; pure. */
27
+ * @complexity O(r) time and space for r required fields; pure. */
26
28
  export function batchItemRequiredFields({ inputSchema }, _optional = {}) {
27
- const items = isPlainObject(inputSchema) && isPlainObject(inputSchema.properties) ? inputSchema.properties.items : undefined;
28
- const text = isPlainObject(items) && typeof items.description === "string" ? items.description : "";
29
- const start = text.indexOf(ITEM_NEEDS);
30
- const end = text.indexOf(ITEM_NEEDS_END, start);
31
- if (start === -1 || end === -1)
29
+ if (!isPlainObject(inputSchema))
32
30
  return [];
33
- return text.slice(start + ITEM_NEEDS.length, end).split(", ");
31
+ const schema = inputSchema;
32
+ return [...(schema[BATCH_ITEM_REQUIRED_FIELDS] ?? [])];
34
33
  }
35
34
  /** Used when a {@link BatchableTool} names no `maxItems`. */
36
35
  export const DEFAULT_MAX_BATCH_ITEMS = 25;
@@ -56,15 +55,16 @@ function isPlainObject(value) {
56
55
  }
57
56
  /**
58
57
  * The descriptor a batchable tool publishes: its own schema plus an `items` array, its top-level
59
- * `required` list moved into the `items` description (a batch call sets those per item or once at
60
- * the top level through the declared legacy normalization), and batch guidance appended to its description.
58
+ * `required` list retained as metadata and described on required properties (a batch call sets
59
+ * those per item or once at the top level through the declared legacy normalization), and batch
60
+ * guidance appended to its description.
61
61
  *
62
62
  * @param required.descriptor - The tool's registered descriptor.
63
63
  * @param required.tool - Its batch settings.
64
64
  * @returns A new descriptor; the input is not mutated.
65
65
  * @throws {Error} If the tool publishes no object schema, or already has an `items` property
66
66
  * (the batch field would shadow it) — both developer errors caught at composition time.
67
- * @complexity O(p) in the schema's top-level property count.
67
+ * @complexity O(p + r) time and space for p top-level properties and r required fields.
68
68
  */
69
69
  export function batchDescriptorFor({ descriptor, tool }, _optional = {}) {
70
70
  const schema = descriptor.inputSchema;
@@ -76,9 +76,18 @@ export function batchDescriptorFor({ descriptor, tool }, _optional = {}) {
76
76
  }
77
77
  const maxItems = tool.maxItems ?? DEFAULT_MAX_BATCH_ITEMS;
78
78
  const requiredFields = schema.required ?? [];
79
+ const requiredNames = new Set(requiredFields);
80
+ const properties = Object.fromEntries(Object.entries(schema.properties).map(([name, property]) => [
81
+ name,
82
+ requiredNames.has(name) && isPlainObject(property)
83
+ ? { ...property, description: `Required for a single call (or set it in each item). ${property.description ?? ""}` }
84
+ : property,
85
+ ]));
79
86
  const rest = { ...schema };
80
87
  delete rest.required;
81
88
  const needs = requiredFields.length > 0 ? `${ITEM_NEEDS}${requiredFields.join(", ")}${ITEM_NEEDS_END}` : "";
89
+ // Inside the removable guidance so search keeps only the authored description and signature.
90
+ const singleNeeds = requiredFields.length > 0 ? `Single call requires: ${requiredFields.join(", ")}. ` : "";
82
91
  const items = {
83
92
  type: "array",
84
93
  minItems: 1,
@@ -91,8 +100,9 @@ export function batchDescriptorFor({ descriptor, tool }, _optional = {}) {
91
100
  ...descriptor,
92
101
  description: `${descriptor.description ?? ""}${BATCH_GUIDANCE_MARKER}to do several at once, pass items: [{...}, ...] (up to ${maxItems}) in ONE call instead of one call per item. ` +
93
102
  "Canonical shape: {items:[{...}, ...]} only. Legacy shared top-level fields are normalized into each item; item values win. " +
103
+ singleNeeds +
94
104
  "Returns { batch: true, outcome: completed | partial_failure | error, total, succeeded, failed, results: [{ index, ok, result | error }] }; one item's failure does not stop the others.",
95
- inputSchema: { ...rest, properties: { ...schema.properties, items } },
105
+ inputSchema: { ...rest, [BATCH_ITEM_REQUIRED_FIELDS]: [...requiredFields], properties: { ...properties, items } },
96
106
  };
97
107
  }
98
108
  /** The domain message without `withSchemaOnRejection`'s appended schema: the text before the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/core",
3
- "version": "0.6.16",
3
+ "version": "0.6.17",
4
4
  "description": "The Jini kernel: typed DI tokens, pack composition and lifecycle, the tool registry, redaction, and origin/API-token auth primitives. Zero dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {