@jini-ai/core 0.6.15-rc.1 → 0.6.15

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +1 -0
  3. package/dist/approval.d.ts +4 -2
  4. package/dist/approval.js +7 -3
  5. package/dist/batch-tool-inputs.js +10 -3
  6. package/dist/contribution-registry.d.ts +23 -0
  7. package/dist/fetch/cache.d.ts +1 -0
  8. package/dist/fetch/cache.js +15 -7
  9. package/dist/index.d.ts +2 -1
  10. package/dist/index.js +1 -1
  11. package/dist/origin-validation.js +9 -8
  12. package/dist/primitives/index.d.ts +1 -0
  13. package/dist/primitives/index.js +1 -0
  14. package/dist/primitives/paths.js +2 -1
  15. package/dist/primitives/sse.js +4 -3
  16. package/dist/primitives/trim-chars.d.ts +25 -0
  17. package/dist/primitives/trim-chars.js +28 -0
  18. package/dist/records.d.ts +29 -6
  19. package/dist/records.js +105 -15
  20. package/dist/redact.d.ts +0 -1
  21. package/dist/redact.js +29 -7
  22. package/dist/registration-kit.js +1 -3
  23. package/dist/settings/agent-tools.js +7 -5
  24. package/dist/settings/agent-value-write-tools.js +7 -3
  25. package/dist/settings/dictionaries/index.d.ts +0 -22
  26. package/dist/settings/dictionaries/index.js +0 -1
  27. package/dist/settings/ensure-definitions.js +4 -2
  28. package/dist/settings/express/http-request.js +2 -1
  29. package/dist/settings/express/http.js +12 -4
  30. package/dist/settings/repo.memory.js +5 -2
  31. package/dist/settings/settings.js +5 -1
  32. package/dist/settings/tool-registrations.js +9 -3
  33. package/dist/settings/write-service.js +11 -9
  34. package/dist/target-scope.js +2 -1
  35. package/dist/text/index.d.ts +2 -0
  36. package/dist/text/index.js +2 -0
  37. package/dist/text/line-tail.d.ts +17 -0
  38. package/dist/text/line-tail.js +25 -0
  39. package/dist/text/sanitize-untrusted-text.js +33 -4
  40. package/dist/tool-exposure.js +20 -16
  41. package/dist/tool-input-normalization.d.ts +11 -3
  42. package/dist/tool-input-normalization.js +14 -8
  43. package/dist/tool-metadata-types.d.ts +5 -0
  44. package/dist/tool-registry.d.ts +5 -0
  45. package/package.json +1 -1
@@ -1,4 +1,3 @@
1
- import type { ToolRegistration } from './tool-registry.js';
2
1
  export { ToolInputNormalizationError } from './tool-input-errors.js';
3
2
  /** A value-free account of canonicalization; domain hooks use the same contract as the gate. */
4
3
  export interface NormalizedToolInput {
@@ -8,8 +7,17 @@ export interface NormalizedToolInput {
8
7
  export type ToolInputNormalizer = (required: {
9
8
  input: Readonly<Record<string, unknown>>;
10
9
  }, optional?: Record<string, never>) => NormalizedToolInput | Promise<NormalizedToolInput>;
10
+ /** Only the registration facts consumed by normalization; carries no execution authority. */
11
+ interface NormalizationRegistration {
12
+ readonly descriptor: {
13
+ readonly id: string;
14
+ readonly inputSchema?: unknown;
15
+ };
16
+ readonly invocationSchema?: unknown;
17
+ readonly normalizeInput?: ToolInputNormalizer;
18
+ }
11
19
  /** Canonicalize one batch layer (including declared aliases) before merging; leave value conversion
12
- * and domain hooks for final normalization. Throws ToolInputError for collisions within this layer, never across
20
+ * and domain hooks for final normalization. Throws ToolInputError for differing colliding values within this layer, never across
13
21
  * layers. Uses the same bounded schema walk as normalizeToolInput.
14
22
  * @example canonicalizeToolInputKeys({ input: { max_chars: '1000' }, schema });
15
23
  */
@@ -28,7 +36,7 @@ export declare function canonicalizeToolInputKeys({ input, schema }: {
28
36
  */
29
37
  export declare function normalizeToolInput({ input, registration }: {
30
38
  input: unknown;
31
- registration: Pick<ToolRegistration, 'descriptor' | 'normalizeInput' | 'invocationSchema'>;
39
+ registration: NormalizationRegistration;
32
40
  }, _options?: Record<string, never>): Promise<NormalizedToolInput>;
33
41
  /** Keep result shapes intact and make rewrite notes visible in plain and MCP tool results. */
34
42
  export declare function withNormalizationNotes({ output, notes }: {
@@ -117,10 +117,14 @@ function unknownKeyError({ key, location, shape }, _options = {}) {
117
117
  const names = [...shape.names.filter(name => required.has(name)), ...shape.names.filter(name => !required.has(name))];
118
118
  const declared = names.map(name => `${name} (${required.has(name) ? 'required' : 'optional'})`).join(', ') || 'none';
119
119
  const hints = names.filter(name => nearMiss({ left: keyShape(key), right: keyShape(name) }));
120
- const suggestion = hints.length ? ` Did you mean ${hints.map(name => `'${name}'`).join(', ')}?` : '';
120
+ const quotedHints = hints.map(name => `'${name}'`).join(', ');
121
+ const suggestion = hints.length ? ` Did you mean ${quotedHints}?` : '';
121
122
  return new ToolInputError({ message: `Unknown input '${location}'. Declared inputs: ${declared}.${suggestion} Resend with the declared name.` });
122
123
  }
123
- /** One key of an object: canonical rename + recursion, closed-schema refusal, or open pass-through. */
124
+ /** One key of an object: canonical rename + recursion, closed-schema refusal, or open pass-through.
125
+ * Agreeing scalar aliases coalesce after coercion; differing values still fail without disclosure.
126
+ * @complexity The bounded child walk plus O(1) source/value checks.
127
+ */
124
128
  function normalizeEntry({ key, raw, shape, sources, step }) {
125
129
  const { path, depth, walk } = step;
126
130
  const location = path ? `${path}.${key}` : key;
@@ -131,13 +135,15 @@ function normalizeEntry({ key, raw, shape, sources, step }) {
131
135
  const childSchema = object(shape.schema.additionalProperties) ? shape.schema.additionalProperties : undefined;
132
136
  return [key, normalizeValue({ value: raw, schema: childSchema, step: { path: location, depth: depth + 1, walk } })];
133
137
  }
134
- const previous = sources.get(target);
135
- if (previous !== undefined)
136
- throw new ToolInputError({ message: `Conflicting inputs '${previous}' and '${key}' both name '${target}'. Send only '${target}'.` });
137
- sources.set(target, key);
138
138
  if (target !== key)
139
139
  walk.notes.push(`${location}→${target}`);
140
- return [target, normalizeValue({ value: raw, schema: shape.properties[target], step: { path: `${path ? `${path}.` : ''}${target}`, depth: depth + 1, walk } })];
140
+ const parentPrefix = path ? `${path}.` : '';
141
+ const value = normalizeValue({ value: raw, schema: shape.properties[target], step: { path: `${parentPrefix}${target}`, depth: depth + 1, walk } });
142
+ const previous = sources.get(target);
143
+ if (previous !== undefined && !Object.is(previous.value, value))
144
+ throw new ToolInputError({ message: `Conflicting inputs '${previous.key}' and '${key}' both name '${target}'. Send only '${target}'.` });
145
+ sources.set(target, { key, value });
146
+ return [target, value];
141
147
  }
142
148
  function normalizeObject({ value, schema, step }) {
143
149
  const properties = object(schema.properties) ? schema.properties : {};
@@ -170,7 +176,7 @@ function walkRoot({ input, schema, notes, validateClosed, keysOnly }) {
170
176
  return normalizeValue({ value: input, schema, step: { path: '', depth: 0, walk: { notes, validateClosed, keysOnly } } });
171
177
  }
172
178
  /** Canonicalize one batch layer (including declared aliases) before merging; leave value conversion
173
- * and domain hooks for final normalization. Throws ToolInputError for collisions within this layer, never across
179
+ * and domain hooks for final normalization. Throws ToolInputError for differing colliding values within this layer, never across
174
180
  * layers. Uses the same bounded schema walk as normalizeToolInput.
175
181
  * @example canonicalizeToolInputKeys({ input: { max_chars: '1000' }, schema });
176
182
  */
@@ -7,6 +7,11 @@ export interface ToolApprovalMetadata {
7
7
  readonly rule?: string;
8
8
  }
9
9
  export interface ToolMetadata<A extends ToolApprovalMetadata = ToolApprovalMetadata> {
10
+ /** Human-facing action name and optional button verb; presentation only, never authority. */
11
+ readonly title?: string;
12
+ /** Plain-language consequence shown before approval; never used to classify or authorize. */
13
+ readonly summary?: string;
14
+ readonly actionVerb?: string;
10
15
  /** Installed guidance capabilities needed by a writer; independent of permission and risk. */
11
16
  readonly guidanceCapabilities?: readonly string[];
12
17
  readonly search?: {
@@ -163,6 +163,11 @@ export interface ToolExecutionContext {
163
163
  /** Optional handler ports supplied by the invoking transport. */
164
164
  export interface ToolExecutionOptions {
165
165
  readonly emitSurface?: SurfaceEmitter;
166
+ /** Reports the human wait to the executor so concurrent writes can be refused. This is
167
+ * notification only; it never supplies a confirmation decision or grants authority. */
168
+ readonly onApprovalStateChange?: (required: {
169
+ pending: boolean;
170
+ }, optional?: Record<string, never>) => void;
166
171
  /** Invoke through the same executor, retaining this call's principal, run, cancellation and
167
172
  * transport gates. Rejects on denial, failed confirmation, validation or execution failure.
168
173
  * A composition-owned registry may retain a source registration behind a derived catalog card.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/core",
3
- "version": "0.6.15-rc.1",
3
+ "version": "0.6.15",
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": {