@manushya/tool-schema-kit
v0.4.0
Published
Utilities for editing and serializing supported API tool input schemas.
Readme
@manushya/tool-schema-kit
Utilities for building, importing, validating, and serializing a focused input-schema model for API tools and LLM tool calling.
This package is framework-independent TypeScript with no runtime dependencies. It is intended for products that need a user-editable schema tree, then need to serialize that tree into a supported JSON Schema subset for tool definitions.
Install
npm install @manushya/tool-schema-kitThe package ships ESM, CommonJS, and TypeScript declarations.
import {
inferTreeFromJson,
parseSupportedSchema,
treeToSchema,
validateTree,
UnsupportedSchemaError,
} from '@manushya/tool-schema-kit';What It Does
tool-schema-kit works with two representations:
SchemaTree: an editing-friendly tree of field nodes.SupportedJsonSchema: the canonical schema output used by tool runtimes.
Use SchemaTree in UI or builder flows. Persist or pass around the serialized JSON Schema from treeToSchema().
Supported Schema Subset
This is not a full JSON Schema implementation. It supports the subset useful for describing tool input shapes:
objectwithproperties- nested objects
string,number,integer,booleanarraywith exactly oneitemsschema- required and optional object properties
- string-only
enumchoices description- nullable primitive and enum fields as
type: [T, "null"]
For nullable enum fields, treeToSchema() also includes null in the emitted enum array so the JSON Schema is valid for a null value:
{
"type": ["string", "null"],
"enum": ["auto", "manual", null]
}Every object emitted by treeToSchema() includes:
{
"additionalProperties": false
}When importing an existing schema with parseSupportedSchema(), omitted additionalProperties and additionalProperties: true are accepted for convenience. The canonical output from treeToSchema() still normalizes every object to additionalProperties: false. Schema-valued additionalProperties is not supported.
Unsupported keywords include $ref, $defs, allOf, oneOf, anyOf, if, then, else, dependentRequired, dependentSchemas, patternProperties, tuple-style arrays, prefixItems, minimum, maximum, multipleOf, minLength, maxLength, and regex pattern.
API
inferTreeFromJson(json)
Creates a best-effort editable tree from an example JSON payload. This function always succeeds once the input is valid parsed JSON.
import { inferTreeFromJson } from '@manushya/tool-schema-kit';
const tree = inferTreeFromJson({
agentId: 'agent_123',
settings: {
brandingEnabled: true,
},
prompts: [
{
text: 'Hello',
icon: 'wave',
},
],
});Inference is intentionally editable:
- all inferred fields default to optional
- integers are guessed with
Number.isInteger() nullvalues become nullable strings- enum values are not inferred automatically
parseSupportedSchema(schema)
Strictly parses an existing supported JSON Schema into a SchemaTree.
import {
parseSupportedSchema,
UnsupportedSchemaError,
} from '@manushya/tool-schema-kit';
try {
const tree = parseSupportedSchema({
type: 'object',
properties: {
agentId: {
type: 'string',
description: 'Agent identifier',
},
startMode: {
type: ['string', 'null'],
enum: ['auto', 'manual', null],
},
},
required: ['agentId'],
additionalProperties: false,
});
} catch (error) {
if (error instanceof UnsupportedSchemaError) {
console.error(error.keyword, error.path);
}
}UnsupportedSchemaError identifies the first unsupported keyword and where it was found, so callers can show precise import errors. If a nullable enum includes null, parseSupportedSchema() records the field as nullable: true and keeps only string choices in FieldNode.enumValues.
For object schemas, omitted additionalProperties and additionalProperties: true are imported successfully. They are normalized to additionalProperties: false the next time the tree is serialized with treeToSchema().
validateTree(tree)
Checks structural correctness before serialization or save.
import { validateTree } from '@manushya/tool-schema-kit';
const result = validateTree(tree);
if (!result.valid) {
console.log(result.errors);
}Validation checks include:
- root node exists and is an object
- referenced child and item nodes exist
- object sibling names are unique
- object child fields have names
- array nodes have one item schema
- enum nodes have at least one value
- nullable is used only on supported field types
treeToSchema(tree)
Serializes a valid SchemaTree into the supported JSON Schema subset.
import { treeToSchema, validateTree } from '@manushya/tool-schema-kit';
const validation = validateTree(tree);
if (!validation.valid) {
throw new Error(validation.errors.join('\n'));
}
const inputSchema = treeToSchema(tree);Example output:
{
"type": "object",
"properties": {
"agentId": {
"type": "string",
"description": "Agent identifier"
},
"startMode": {
"type": ["string", "null"],
"enum": ["auto", "manual", null]
}
},
"required": ["agentId"],
"additionalProperties": false
}Types
export type FieldType =
| 'string'
| 'number'
| 'integer'
| 'boolean'
| 'object'
| 'array'
| 'enum';
export interface FieldNode {
id: string;
name: string;
type: FieldType;
description?: string;
required?: boolean;
nullable?: boolean;
enumValues?: string[];
childIds?: string[];
itemId?: string;
}
export interface SchemaTree {
rootId: string;
nodes: Record<string, FieldNode>;
}
export interface SupportedJsonSchema {
type: string | string[];
description?: string;
properties?: Record<string, SupportedJsonSchema>;
required?: string[];
additionalProperties?: boolean;
items?: SupportedJsonSchema;
enum?: Array<string | null>;
}Development
npm install
npm test
npm run buildBuild output is written to dist/.
