standard-tool 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andrey Gubanov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # standard-tool
2
+ [![npm](https://img.shields.io/npm/v/standard-tool)](https://www.npmjs.com/package/standard-tool) [![CI](https://github.com/finom/standard-tool/actions/workflows/ci.yml/badge.svg)](https://github.com/finom/standard-tool/actions/workflows/ci.yml)
3
+
4
+ > A **standalone**, dependency-free convention for defining LLM tools — built on [Standard Schema](https://standardschema.dev) + [Standard JSON Schema](https://standardschema.dev/json-schema).
5
+
6
+ `standard-tool` is one tiny function that gives an LLM tool a single, neutral shape: a `name`, a `description`, an `execute` function, and `inputSchema`/`outputSchema` that both **validate** their data (Standard Schema) and **emit JSON Schema** for the model (Standard JSON Schema). No framework, no runtime dependencies — copy-paste it or `npm i standard-tool`.
7
+
8
+ It's intended as a **community-wide standard** — the same way [Standard Schema](https://standardschema.dev) became a shared validation interface across Zod, Valibot, and ArkType, and the way the [Vercel AI SDK](https://ai-sdk.dev) popularized a common tool definition. The idea is one neutral contract that any library, framework, or app can **produce or consume**, instead of every project reinventing its own incompatible tool object.
9
+
10
+ ```ts
11
+ import { standardTool } from 'standard-tool';
12
+ import { z } from 'zod';
13
+
14
+ const getWeather = standardTool({
15
+ name: 'get_weather',
16
+ description: 'Current temperature for a city',
17
+ inputSchema: z.object({ city: z.string() }),
18
+ outputSchema: z.object({ tempC: z.number() }),
19
+ execute: async ({ city }) => ({ tempC: 21 }), // `city` is typed; the return is validated
20
+ });
21
+
22
+ await getWeather.execute({ city: 'Paris' }); // → { tempC: number } | { error: string }; validated in & out (errors → { error } by default)
23
+ ```
24
+
25
+ ## What it is
26
+
27
+ - **Standalone & dependency-free.** A single, small function. The Standard Schema and Standard JSON Schema interfaces are vendored into the package, so installing it pulls in nothing else — and you can just copy the source into your project instead (see [below](#or-just-copy-paste-it)).
28
+ - **A convention, not a framework.** It doesn't run your agent, call your model, or own your runtime. It defines only the shape — `{ name, description, inputSchema?, outputSchema?, execute }` — and the things every tool needs: validation, a JSON Schema, and a model-facing result.
29
+ - **Validates input _and_ output.** `execute` accepts untrusted input (e.g. JSON arguments from a model), validates it via Standard Schema (when you provide a schema — both are optional), runs your logic, then validates the result. **By default** a validation failure or a thrown error doesn't propagate — it comes back as `{ error: string }`, so a model loop keeps running; pass a `formatOutput` to reshape that (or to re-throw).
30
+ - **Emits JSON Schema for any model.** Because the schemas implement Standard JSON Schema, you get an OpenAI- or MCP-ready JSON Schema (any function-calling model) synchronously via `inputSchema['~standard'].jsonSchema.input(...)`.
31
+
32
+ ## Why
33
+
34
+ Every LLM framework ships its own tool object — Vercel AI SDK, MCP, oRPC, Effect — each a different shape, none portable, most welded to the framework. But the hard part — schema interop — is **already** standardized: Standard Schema for validation and Standard JSON Schema for JSON Schema emission. `standard-tool` is the missing, neutral wrapper around them: small enough to become a shared convention rather than another framework lock-in.
35
+
36
+ ## Install
37
+
38
+ ```sh
39
+ npm i standard-tool
40
+ # bring any library that implements BOTH Standard Schema and Standard JSON Schema:
41
+ npm i zod # 4.2+ (or `arktype` 2.1.28+, or `valibot` + `@valibot/to-json-schema`)
42
+ ```
43
+
44
+ ## Or just copy-paste it
45
+
46
+ No dependency at all. Paste this and import the spec types from the official, types-only [`@standard-schema/spec`](https://github.com/standard-schema/standard-schema) (`npm i -D @standard-schema/spec`):
47
+
48
+ ```ts
49
+ import type { StandardSchemaV1, StandardJSONSchemaV1 } from '@standard-schema/spec';
50
+
51
+ type CombinedSchema<T> = StandardSchemaV1<T> & StandardJSONSchemaV1<T>;
52
+
53
+ export interface StandardTool<Input, Output, FormattedOutput = Output | { error: string }> {
54
+ name: string;
55
+ description: string;
56
+ inputSchema?: CombinedSchema<Input>;
57
+ outputSchema?: CombinedSchema<Output>;
58
+ execute(input: Input): FormattedOutput | Promise<FormattedOutput>;
59
+ }
60
+
61
+ export function standardTool<Input, Output, FormattedOutput = Output | { error: string }>(def: {
62
+ name: string;
63
+ description: string;
64
+ inputSchema?: CombinedSchema<Input>;
65
+ outputSchema?: CombinedSchema<Output>;
66
+ execute: (input: Input) => Output | Promise<Output>;
67
+ formatOutput?: (result: Output | Error) => FormattedOutput | Promise<FormattedOutput>;
68
+ }): StandardTool<Input, Output, FormattedOutput> {
69
+ const check = async <T>(where: 'input' | 'output', s: CombinedSchema<T>, v: unknown): Promise<T> => {
70
+ const r = await s['~standard'].validate(v);
71
+ // a validation failure is a plain Error carrying the Standard Schema issues — no dedicated type:
72
+ if (r.issues) throw Object.assign(new Error(`${where} validation failed`), { issues: r.issues });
73
+ return r.value;
74
+ };
75
+ const formatOutput =
76
+ def.formatOutput ??
77
+ ((result: Output | Error) => (result instanceof Error ? { error: result.message } : result) as unknown as FormattedOutput);
78
+ return {
79
+ name: def.name,
80
+ description: def.description,
81
+ inputSchema: def.inputSchema,
82
+ outputSchema: def.outputSchema,
83
+ async execute(input) {
84
+ let result: Output | Error;
85
+ try {
86
+ const validInput = def.inputSchema ? await check('input', def.inputSchema, input) : input;
87
+ const output = await def.execute(validInput);
88
+ result = def.outputSchema ? await check('output', def.outputSchema, output) : output;
89
+ } catch (e) {
90
+ result = e instanceof Error ? e : new Error(String(e));
91
+ }
92
+ return formatOutput(result);
93
+ },
94
+ };
95
+ }
96
+ ```
97
+
98
+ ## API
99
+
100
+ ```ts
101
+ import { standardTool, type StandardTool, type FormatOutputFn } from 'standard-tool';
102
+
103
+ standardTool(def): StandardTool<Input, Output, FormattedOutput>;
104
+ ```
105
+
106
+ `Input`/`Output` are your **data types** (what your `execute` accepts and returns); the optional schemas describe them. `FormattedOutput` is what the tool hands the model after formatting — `Output | { error: string }` by default.
107
+
108
+ | field | type | purpose |
109
+ | --- | --- | --- |
110
+ | `name` | `string` | tool name sent to the model |
111
+ | `description` | `string` | what the tool does |
112
+ | `inputSchema?` | `CombinedSchema<Input>` | optional input schema — validates **and** emits JSON Schema |
113
+ | `outputSchema?` | `CombinedSchema<Output>` | optional output schema — validates **and** emits JSON Schema |
114
+ | `execute` (yours) | `(input: Input) => Output \| Promise<Output>` | your logic — receives validated input, returns the output |
115
+ | `execute` (tool) | `(input: Input) => FormattedOutput \| Promise<FormattedOutput>` | validate in → run yours → validate out → format; errors become the output (no throw) **by default** |
116
+ | `formatOutput?` | `(result: Output \| Error) => FormattedOutput` | optional; maps the result — or an `Error` carrying `issues` — to the model output. Default `result instanceof Error ? { error: result.message } : result` |
117
+
118
+ `inputSchema`/`outputSchema` are optional; when present they must implement both Standard Schema and Standard JSON Schema (Zod 4.2+, ArkType 2.1.28+, or Valibot 1.2+ via `@valibot/to-json-schema`) — `Input`/`Output` are inferred from them (or from `execute` when a schema is omitted).
119
+
120
+ `standardTool` is deliberately a **thin utility**: `name`, `description`, `inputSchema`, and `outputSchema` are returned **exactly as you passed them**. Only `execute` is wrapped — it validates input and output (when schemas are present), then routes the result, or any thrown error (a validation failure is a plain `Error` carrying `issues`), through `formatOutput`. `formatOutput` defaults to the `{ error }` envelope so bad data doesn't throw and a model loop keeps going; supply your own to reshape the output (its return type becomes the tool's `FormattedOutput`) or to throw and surface the error. Note `formatOutput` is a **creation-time argument, not a field** on the returned tool — the shape stays the minimal `{ name, description, inputSchema?, outputSchema?, execute }`. That's the whole job.
121
+
122
+ ## Usage
123
+
124
+ ```ts
125
+ import { standardTool } from 'standard-tool';
126
+ import { z } from 'zod';
127
+
128
+ const getWeather = standardTool({
129
+ name: 'get_weather',
130
+ description: 'Current temperature for a city',
131
+ inputSchema: z.object({ city: z.string() }),
132
+ outputSchema: z.object({ tempC: z.number() }),
133
+ execute: async ({ city }) => ({ tempC: 21 }),
134
+ });
135
+
136
+ // validated end to end — by default, bad input or output comes back as { error: string } (override via formatOutput):
137
+ const out = await getWeather.execute({ city: 'Paris' }); // { tempC: number } | { error: string }
138
+
139
+ // JSON Schema for the model (Standard JSON Schema), synchronous (inputSchema is optional, hence `!`):
140
+ const parameters = getWeather.inputSchema!['~standard'].jsonSchema.input({ target: 'draft-2020-12' });
141
+ ```
142
+
143
+ ## With the OpenAI API
144
+
145
+ Uses the [Responses API](https://developers.openai.com/api/docs/guides/function-calling). Because every tool is the same neutral shape, you keep them in one array: `.map` it into the request's `tools`, then dispatch each function call back to the matching tool by `name`. Adding a fourth tool is one more array entry — no special-casing, no per-tool wiring. And because `execute` returns `{ error }` instead of throwing **by default**, a malformed tool call comes back to the model to self-correct rather than crashing your loop (a custom `formatOutput` can opt back into throwing).
146
+
147
+ ```ts
148
+ import OpenAI from 'openai';
149
+ import { z } from 'zod';
150
+ import { standardTool, type StandardTool } from 'standard-tool';
151
+
152
+ const client = new OpenAI();
153
+
154
+ const tools: StandardTool<unknown, unknown>[] = [
155
+ standardTool({
156
+ name: 'get_weather',
157
+ description: 'Get the current temperature for a city',
158
+ inputSchema: z.object({ city: z.string() }),
159
+ outputSchema: z.object({ tempC: z.number() }),
160
+ execute: async ({ city }) => ({ tempC: 21 }),
161
+ }),
162
+ standardTool({
163
+ name: 'get_time',
164
+ description: 'Get the current time in an IANA timezone',
165
+ inputSchema: z.object({ timezone: z.string() }),
166
+ outputSchema: z.object({ iso: z.string() }),
167
+ execute: async ({ timezone }) => ({ iso: new Date().toLocaleString('en-US', { timeZone: timezone }) }),
168
+ }),
169
+ standardTool({
170
+ name: 'convert_currency',
171
+ description: 'Convert an amount between two currencies',
172
+ inputSchema: z.object({ amount: z.number(), from: z.string(), to: z.string() }),
173
+ outputSchema: z.object({ amount: z.number() }),
174
+ execute: async ({ amount }) => ({ amount: Math.round(amount * 1.08 * 100) / 100 }),
175
+ }),
176
+ ];
177
+
178
+ const input: OpenAI.Responses.ResponseInput = [{ role: 'user', content: 'What is the weather in Paris?' }];
179
+
180
+ const res = await client.responses.create({
181
+ model: 'gpt-5',
182
+ input,
183
+ // ← the payoff: one shape, one mapping for every tool
184
+ tools: tools.map((tool): OpenAI.Responses.Tool => ({
185
+ type: 'function',
186
+ name: tool.name,
187
+ description: tool.description,
188
+ parameters: tool.inputSchema ? tool.inputSchema['~standard'].jsonSchema.input({ target: 'draft-2020-12' }) : {},
189
+ strict: false,
190
+ })),
191
+ });
192
+
193
+ input.push(...res.output);
194
+
195
+ for (const item of res.output) {
196
+ if (item.type !== 'function_call') continue;
197
+ const tool = tools.find((t) => t.name === item.name);
198
+ if (!tool) continue;
199
+ const result = await tool.execute(JSON.parse(item.arguments)); // validates args + result; bad args → { error } by default
200
+ input.push({ type: 'function_call_output', call_id: item.call_id, output: JSON.stringify(result) });
201
+ }
202
+
203
+ const final = await client.responses.create({ model: 'gpt-5', input });
204
+ console.log(final.output_text);
205
+ ```
206
+
207
+ ## Links
208
+
209
+ - **Standard Schema** — https://standardschema.dev
210
+ - **Standard JSON Schema** — https://standardschema.dev/json-schema
211
+ - **@standard-schema/spec** — https://github.com/standard-schema/standard-schema
212
+
213
+ ## License
214
+
215
+ MIT © Andrey Gubanov
@@ -0,0 +1,53 @@
1
+ import type { CombinedSchema } from './standard-schema.js';
2
+ export type * from './standard-schema.js';
3
+ /** The default formatted output: your `Output`, or an `{ error }` envelope when execution or validation failed. */
4
+ export type DefaultFormattedOutput<Output> = Output | {
5
+ error: string;
6
+ };
7
+ /**
8
+ * Maps a raw tool result — your `Output`, or an `Error` (carrying `issues` when a Standard Schema
9
+ * validation failed) — to the formatted output. Return an envelope to keep a model loop running,
10
+ * or throw to surface the error.
11
+ */
12
+ export type FormatOutputFn<Output, FormattedOutput> = (result: Output | Error) => FormattedOutput | Promise<FormattedOutput>;
13
+ /**
14
+ * A standard, DRY LLM tool over its **data** types `Input`/`Output`: `name` + `description` +
15
+ * optional Standard-Schema/JSON-Schema `inputSchema`/`outputSchema` + `execute(input: Input)`.
16
+ * `FormattedOutput` is what `execute` returns to the model after formatting — by default
17
+ * {@link DefaultFormattedOutput}, i.e. the data or an `{ error }` envelope.
18
+ */
19
+ export interface StandardTool<Input, Output, FormattedOutput = DefaultFormattedOutput<Output>> {
20
+ name: string;
21
+ description: string;
22
+ /** Optional Standard Schema + Standard JSON Schema describing the input data. */
23
+ inputSchema?: CombinedSchema<Input>;
24
+ /** Optional Standard Schema + Standard JSON Schema describing the output data. */
25
+ outputSchema?: CombinedSchema<Output>;
26
+ /**
27
+ * Validate input (when `inputSchema`) → run your logic → validate output (when `outputSchema`) →
28
+ * format. **By default it doesn't throw**: a validation failure or a thrown error becomes the
29
+ * formatted output (`{ error: string }`) — unless your `formatOutput` throws — so a model loop
30
+ * keeps running.
31
+ */
32
+ execute(input: Input): FormattedOutput | Promise<FormattedOutput>;
33
+ }
34
+ /**
35
+ * Create a standard tool. `inputSchema`/`outputSchema` are optional; when present they must implement
36
+ * both Standard Schema (validation) and Standard JSON Schema (JSON Schema emission) — e.g. Zod 4.2+,
37
+ * ArkType 2.1.28+, or Valibot 1.2+ via `@valibot/to-json-schema`.
38
+ *
39
+ * Your `execute` receives the (validated) input and returns the output. The returned tool's `execute`
40
+ * validates input, runs yours, validates the result, then formats it via `formatOutput` — which by
41
+ * default turns any error into `{ error: message }` instead of throwing, so a model loop keeps going.
42
+ * Pass your own `formatOutput` to reshape the output (its return type becomes the tool's `FormattedOutput`)
43
+ * or to throw and surface the error. Validation failures are plain `Error`s carrying an `issues` array.
44
+ */
45
+ export declare function standardTool<Input, Output, FormattedOutput = DefaultFormattedOutput<Output>>(def: {
46
+ name: string;
47
+ description: string;
48
+ inputSchema?: CombinedSchema<Input>;
49
+ outputSchema?: CombinedSchema<Output>;
50
+ execute: (input: Input) => Output | Promise<Output>;
51
+ formatOutput?: FormatOutputFn<Output, FormattedOutput>;
52
+ }): StandardTool<Input, Output, FormattedOutput>;
53
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,sBAAsB,CAAC;AAE7E,mBAAmB,sBAAsB,CAAC;AAE1C,mHAAmH;AACnH,MAAM,MAAM,sBAAsB,CAAC,MAAM,IAAI,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE;;;;GAIG;AACH,MAAM,MAAM,cAAc,CAAC,MAAM,EAAE,eAAe,IAAI,CACpD,MAAM,EAAE,MAAM,GAAG,KAAK,KACnB,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,WAAW,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,GAAG,sBAAsB,CAAC,MAAM,CAAC;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,WAAW,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IACpC,kFAAkF;IAClF,YAAY,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACtC;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,GAAG,sBAAsB,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE;IACjG,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IACpC,YAAY,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,YAAY,CAAC,EAAE,cAAc,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACxD,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,CAqB/C"}
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Create a standard tool. `inputSchema`/`outputSchema` are optional; when present they must implement
3
+ * both Standard Schema (validation) and Standard JSON Schema (JSON Schema emission) — e.g. Zod 4.2+,
4
+ * ArkType 2.1.28+, or Valibot 1.2+ via `@valibot/to-json-schema`.
5
+ *
6
+ * Your `execute` receives the (validated) input and returns the output. The returned tool's `execute`
7
+ * validates input, runs yours, validates the result, then formats it via `formatOutput` — which by
8
+ * default turns any error into `{ error: message }` instead of throwing, so a model loop keeps going.
9
+ * Pass your own `formatOutput` to reshape the output (its return type becomes the tool's `FormattedOutput`)
10
+ * or to throw and surface the error. Validation failures are plain `Error`s carrying an `issues` array.
11
+ */
12
+ export function standardTool(def) {
13
+ const formatOutput = def.formatOutput ??
14
+ ((result) => (result instanceof Error ? { error: result.message } : result));
15
+ return {
16
+ name: def.name,
17
+ description: def.description,
18
+ inputSchema: def.inputSchema,
19
+ outputSchema: def.outputSchema,
20
+ async execute(input) {
21
+ let result;
22
+ try {
23
+ const validInput = def.inputSchema ? await validate('input', def.inputSchema, input) : input;
24
+ const output = await def.execute(validInput);
25
+ result = def.outputSchema ? await validate('output', def.outputSchema, output) : output;
26
+ }
27
+ catch (error) {
28
+ result = error instanceof Error ? error : new Error(String(error));
29
+ }
30
+ return formatOutput(result);
31
+ },
32
+ };
33
+ }
34
+ async function validate(target, schema, value) {
35
+ const result = await schema['~standard'].validate(value); // await covers sync + async
36
+ if (result.issues) {
37
+ // A plain Error carrying the Standard Schema issues — no dedicated error type needed.
38
+ throw Object.assign(new Error(`${target} validation failed: ${result.issues.map((i) => i.message).join('; ')}`), {
39
+ issues: result.issues,
40
+ });
41
+ }
42
+ return result.value;
43
+ }
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAsCA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAkE,GAO7F;IACC,MAAM,YAAY,GAChB,GAAG,CAAC,YAAY;QAChB,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAA+B,CAAC,CAAC;IAC7G,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,IAAI,MAAsB,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBAC7F,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC7C,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAC1F,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,QAAQ,CACrB,MAA0B,EAC1B,MAAS,EACT,KAAc;IAEd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,4BAA4B;IACtF,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,sFAAsF;QACtF,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,MAAM,uBAAuB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YAC/G,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Vendored Standard Schema + Standard JSON Schema interfaces — inlined so this package has ZERO dependencies.
3
+ * Source: https://github.com/standard-schema/standard-schema (MIT) + https://standardschema.dev/json-schema
4
+ * Identical to the @standard-schema/spec types; vendored here for copy-paste + dependency-free installs.
5
+ */
6
+ /** The Standard Typed interface. This is a base type extended by other specs. */
7
+ export interface StandardTypedV1<Input = unknown, Output = Input> {
8
+ /** The Standard properties. */
9
+ readonly '~standard': StandardTypedV1.Props<Input, Output>;
10
+ }
11
+ export declare namespace StandardTypedV1 {
12
+ /** The Standard Typed properties interface. */
13
+ interface Props<Input = unknown, Output = Input> {
14
+ /** The version number of the standard. */
15
+ readonly version: 1;
16
+ /** The vendor name of the schema library. */
17
+ readonly vendor: string;
18
+ /** Inferred types associated with the schema. */
19
+ readonly types?: Types<Input, Output> | undefined;
20
+ }
21
+ /** The Standard Typed types interface. */
22
+ interface Types<Input = unknown, Output = Input> {
23
+ /** The input type of the schema. */
24
+ readonly input: Input;
25
+ /** The output type of the schema. */
26
+ readonly output: Output;
27
+ }
28
+ /** Infers the input type of a Standard Typed. */
29
+ type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema['~standard']['types']>['input'];
30
+ /** Infers the output type of a Standard Typed. */
31
+ type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema['~standard']['types']>['output'];
32
+ }
33
+ /** The Standard Schema interface. */
34
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
35
+ /** The Standard Schema properties. */
36
+ readonly '~standard': StandardSchemaV1.Props<Input, Output>;
37
+ }
38
+ export declare namespace StandardSchemaV1 {
39
+ /** The Standard Schema properties interface. */
40
+ interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
41
+ /** Validates unknown input values. */
42
+ readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
43
+ }
44
+ /** The result interface of the validate function. */
45
+ type Result<Output> = SuccessResult<Output> | FailureResult;
46
+ /** The result interface if validation succeeds. */
47
+ interface SuccessResult<Output> {
48
+ /** The typed output value. */
49
+ readonly value: Output;
50
+ /** A falsy value for `issues` indicates success. */
51
+ readonly issues?: undefined;
52
+ }
53
+ interface Options {
54
+ /** Explicit support for additional vendor-specific parameters, if needed. */
55
+ readonly libraryOptions?: Record<string, unknown> | undefined;
56
+ }
57
+ /** The result interface if validation fails. */
58
+ interface FailureResult {
59
+ /** The issues of failed validation. */
60
+ readonly issues: ReadonlyArray<Issue>;
61
+ }
62
+ /** The issue interface of the failure output. */
63
+ interface Issue {
64
+ /** The error message of the issue. */
65
+ readonly message: string;
66
+ /** The path of the issue, if any. */
67
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
68
+ }
69
+ /** The path segment interface of the issue. */
70
+ interface PathSegment {
71
+ /** The key representing a path segment. */
72
+ readonly key: PropertyKey;
73
+ }
74
+ /** The Standard types interface. */
75
+ interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {
76
+ }
77
+ /** Infers the input type of a Standard. */
78
+ type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
79
+ /** Infers the output type of a Standard. */
80
+ type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
81
+ }
82
+ /** The Standard JSON Schema interface. */
83
+ export interface StandardJSONSchemaV1<Input = unknown, Output = Input> {
84
+ /** The Standard JSON Schema properties. */
85
+ readonly '~standard': StandardJSONSchemaV1.Props<Input, Output>;
86
+ }
87
+ export declare namespace StandardJSONSchemaV1 {
88
+ /** The Standard JSON Schema properties interface. */
89
+ interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
90
+ /** Methods for generating the input/output JSON Schema. */
91
+ readonly jsonSchema: StandardJSONSchemaV1.Converter;
92
+ }
93
+ /** The Standard JSON Schema converter interface. */
94
+ interface Converter {
95
+ /** Converts the input type to JSON Schema. May throw if conversion is not supported. */
96
+ readonly input: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
97
+ /** Converts the output type to JSON Schema. May throw if conversion is not supported. */
98
+ readonly output: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
99
+ }
100
+ /**
101
+ * The target version of the generated JSON Schema.
102
+ *
103
+ * It is *strongly recommended* that implementers support `"draft-2020-12"` and `"draft-07"`, as they are both in wide use. All other targets can be implemented on a best-effort basis. Libraries should throw if they don't support a specified target.
104
+ *
105
+ * The `"openapi-3.0"` target is intended as a standardized specifier for OpenAPI 3.0 which is a superset of JSON Schema `"draft-04"`.
106
+ */
107
+ type Target = 'draft-2020-12' | 'draft-07' | 'openapi-3.0' | ({} & string);
108
+ /** The options for the input/output methods. */
109
+ interface Options {
110
+ /** Specifies the target version of the generated JSON Schema. Support for all versions is on a best-effort basis. If a given version is not supported, the library should throw. */
111
+ readonly target: Target;
112
+ /** Explicit support for additional vendor-specific parameters, if needed. */
113
+ readonly libraryOptions?: Record<string, unknown> | undefined;
114
+ }
115
+ /** The Standard types interface. */
116
+ interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {
117
+ }
118
+ /** Infers the input type of a Standard. */
119
+ type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
120
+ /** Infers the output type of a Standard. */
121
+ type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
122
+ }
123
+ /** Props of a schema that implements BOTH Standard Schema and Standard JSON Schema. */
124
+ export interface CombinedProps<Input = unknown, Output = Input> extends StandardSchemaV1.Props<Input, Output>, StandardJSONSchemaV1.Props<Input, Output> {
125
+ }
126
+ /**
127
+ * A schema that BOTH validates (Standard Schema) and emits JSON Schema (Standard JSON Schema).
128
+ * Natively implemented by Zod 4.2+, ArkType 2.1.28+, Valibot 1.2+ (via @valibot/to-json-schema), and Vovk.
129
+ */
130
+ export interface CombinedSchema<Input = unknown, Output = Input> {
131
+ readonly '~standard': CombinedProps<Input, Output>;
132
+ }
133
+ export declare namespace CombinedSchema {
134
+ type Target = StandardJSONSchemaV1.Target;
135
+ type InferInput<T extends StandardSchemaV1> = StandardSchemaV1.InferInput<T>;
136
+ type InferOutput<T extends StandardSchemaV1> = StandardSchemaV1.InferOutput<T>;
137
+ type SuccessResult<T> = StandardSchemaV1.SuccessResult<T>;
138
+ }
139
+ //# sourceMappingURL=standard-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema.d.ts","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Vendored Standard Schema + Standard JSON Schema interfaces — inlined so this package has ZERO dependencies.
3
+ * Source: https://github.com/standard-schema/standard-schema (MIT) + https://standardschema.dev/json-schema
4
+ * Identical to the @standard-schema/spec types; vendored here for copy-paste + dependency-free installs.
5
+ */
6
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
7
+ /* eslint-disable @typescript-eslint/no-namespace */
8
+ // #########################
9
+ // ### Standard Typed ###
10
+ // #########################
11
+ export {};
12
+ //# sourceMappingURL=standard-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema.js","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4DAA4D;AAC5D,oDAAoD;AACpD,4BAA4B;AAC5B,4BAA4B;AAC5B,4BAA4B"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "standard-tool",
3
+ "version": "0.0.1",
4
+ "description": "Standard DRY LLM Tool Interface — name/description/execute with input & output validated via Standard Schema and emitted as JSON Schema via Standard JSON Schema. Zero dependencies.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "prepare": "tsc",
20
+ "typecheck": "tsc -p tsconfig.test.json",
21
+ "lint": "biome check",
22
+ "lint:fix": "biome check --write",
23
+ "test": "npm run build && npm run typecheck && npm run lint && node --test",
24
+ "patch": "npm test && npm version patch",
25
+ "postversion": "npm run build && npm publish"
26
+ },
27
+ "keywords": [
28
+ "standard-schema",
29
+ "standard-json-schema",
30
+ "json-schema",
31
+ "llm",
32
+ "tool",
33
+ "function-calling",
34
+ "openai",
35
+ "mcp",
36
+ "validation",
37
+ "zod",
38
+ "valibot",
39
+ "arktype"
40
+ ],
41
+ "author": "Andrey Gubanov",
42
+ "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/finom/standard-tool.git"
46
+ },
47
+ "homepage": "https://github.com/finom/standard-tool#readme",
48
+ "bugs": {
49
+ "url": "https://github.com/finom/standard-tool/issues"
50
+ },
51
+ "devDependencies": {
52
+ "@biomejs/biome": "^2.4.16",
53
+ "@types/node": "^25.9.1",
54
+ "typescript": "^6.0.2"
55
+ }
56
+ }