@jini-ai/core 0.4.6 → 0.4.7

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,9 @@
1
1
  # @jini-ai/core
2
2
 
3
+ ## 0.4.7 — 2026-10-16
4
+
5
+ - `requireString`, `requireNumber` and `requireObject` errors list the keys the call actually received and flag unsupported `items[]` batching (a6ac9d7e, c7557838).
6
+
3
7
  ## 0.4.6 — 2026-10-14
4
8
 
5
9
  - Express 5 accepted: the optional `express` peer is now `^4.21.0 || ^5.0.0` (1442d875), so an Express 5 host no longer hits ERESOLVE.
@@ -139,6 +139,11 @@ export declare function indexCatalogById<T extends {
139
139
  export declare function requireInputRecord(required: {
140
140
  input: unknown;
141
141
  }, _optional?: Record<string, never>): Record<string, unknown>;
142
+ /**
143
+ * Reads a required non-empty string, with received-key hints when the field is missing.
144
+ * @throws {ToolInputError} If the field is missing, empty, or not a string.
145
+ * @complexity O(k) for k input keys on a missing-field rejection; otherwise O(1).
146
+ */
142
147
  export declare function requireString(required: {
143
148
  input: Record<string, unknown>;
144
149
  key: string;
@@ -110,11 +110,33 @@ export function requireInputRecord(required, _optional = {}) {
110
110
  throw new ToolInputError({ message: "input must be an object" });
111
111
  return candidate.value;
112
112
  }
113
+ /**
114
+ * Builds received-key and unsupported-batching hints for a missing required field.
115
+ * @complexity O(k) for k input keys.
116
+ */
117
+ function missingFieldHint(required, _optional = {}) {
118
+ const { input } = required;
119
+ // Show names, never values, so a wrong-key or batch call can be corrected without exposing content.
120
+ const keys = Object.keys(input);
121
+ let hint = keys.length > 0 ? `; received: ${keys.join(", ")}` : "";
122
+ if (Array.isArray(input.items)) {
123
+ hint += "; this tool takes one input per call — items[] batching is not supported here";
124
+ }
125
+ return hint;
126
+ }
127
+ /**
128
+ * Reads a required non-empty string, with received-key hints when the field is missing.
129
+ * @throws {ToolInputError} If the field is missing, empty, or not a string.
130
+ * @complexity O(k) for k input keys on a missing-field rejection; otherwise O(1).
131
+ */
113
132
  export function requireString(required, _optional = {}) {
114
133
  const { input, key } = required;
115
134
  const value = input[key];
116
135
  if (typeof value !== "string" || value.length === 0) {
117
- throw new ToolInputError({ message: `'${key}' (non-empty string) is required` });
136
+ let message = `'${key}' (non-empty string) is required`;
137
+ if (value === undefined)
138
+ message += missingFieldHint({ input });
139
+ throw new ToolInputError({ message });
118
140
  }
119
141
  return value;
120
142
  }
@@ -122,7 +144,10 @@ export function requireNumber(requiredArgs, optionalArgs = {}) {
122
144
  const { input, key } = requiredArgs;
123
145
  const value = input[key];
124
146
  if (typeof value !== "number" || !Number.isFinite(value)) {
125
- throw new ToolInputError({ message: `'${key}' (number) is required` });
147
+ let message = `'${key}' (number) is required`;
148
+ if (value === undefined)
149
+ message += missingFieldHint({ input });
150
+ throw new ToolInputError({ message });
126
151
  }
127
152
  return value;
128
153
  }
@@ -131,7 +156,10 @@ export function requireObject(requiredArgs, optionalArgs = {}) {
131
156
  const value = input[key];
132
157
  const candidate = { value };
133
158
  if (!isRecord(candidate) || Array.isArray(candidate.value)) {
134
- throw new ToolInputError({ message: `'${key}' (object) is required` });
159
+ let message = `'${key}' (object) is required`;
160
+ if (value === undefined)
161
+ message += missingFieldHint({ input });
162
+ throw new ToolInputError({ message });
135
163
  }
136
164
  return candidate.value;
137
165
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/core",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
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": {