Skip to content
PluginStats

@gnldev/tool-schema weekly downloads statistics

By gnldev (7 listings) · npm · AI SDKs

Provider-specific tool-schema compatibility layer (OpenAI/Gemini/Anthropic). Extensible ToolSchemaRule + opt-in default set; opt-in with @gnldev/durable.

View on npm Fresh · Oct 18, 2026

@gnldev/tool-schema has 378 recorded weekly downloads on npm, ranking #1593 of 2,322 tracked listings.

Weekly downloads
378
Official API · Oct 18, 2026
7-day growth
—
Insufficient history
30-day growth
—
Insufficient history
90-day growth
—
Insufficient history
Rank
#1593
Among tracked npm listings

About @gnldev/tool-schema

@gnldev/tool-schema

Tool schemas that one provider accepts and another rejects, smoothed over.

The same JSON Schema does not travel cleanly between OpenAI, Gemini and Anthropic: one rejects format on strings, another dislikes certain nested constructs. This package rewrites a tool's schema for the model actually being called.

Install

Install: pnpm add @gnldev/tool-schema — or use it from a repo clone: pnpm install && pnpm -r build.

npm i @gnldev/tool-schema

Use

It is opt-in from @gnldev/durable:

import { defaultRules } from '@gnldev/tool-schema';

const gnl = createGnl({ ...config, schemaCompat: defaultRules });
// or per call: runDurable({ runId, journal, model, tools, schemaCompat: true, prompt })

Or directly:

import { applyToolCompat, detectModel, defaultRules } from '@gnldev/tool-schema';

const safe = applyToolCompat(tools, detectModel(modelId), defaultRules);

Exports

ExportWhat it is
detectModelModel id → which provider family it belongs to
applyToolCompatApplies the matching rules to a tool set
shapeToolDefinitionsThe same rules on the AI SDK's converted tool list, for a model chosen at call time (what @gnldev/durable uses per fallback candidate)
chainToolCompatBoth halves for a model chosen at call time: shape (per candidate) and tools whose validators read an invited null back through what that candidate was sent
ToolSchemaErrorA rule's refusal (e.g. strict: true with an open object under OpenAI); it propagates instead of skipping the rule
defaultRulesThe bundled rule set (OpenAI / Gemini / Anthropic)
ToolSchemaRuleThe rule interface — add your own for a provider not covered here. transform(schema, model, ctx): a rule that widens a node to accept null as "not supplied" calls ctx.nullMeansAbsent(node)

Rules are ordinary objects, so a provider the default set does not know about is a rule you write rather than a fork you maintain.

What the model is told changes; what the tool accepts does not

The rules rewrite the schema sent to the model. The tool still validates with its own schema: zod checks, .default() and .transform() run as they do without this package, so execute receives the same value with compat on or off, and invalid input never reaches it. A tool given as jsonSchema() without a validate stays unvalidated, as it was.

One thing the OpenAI rule changes that you will see

OpenAI's strict mode has no notion of an optional property: every key of an object must be listed in required. So the rule lists them all — and widens the ones that were optional to also accept null, which is the only way strict mode can express "not supplied":

z.object({ to: z.string(), cc: z.string().optional() })
→  required: ["to", "cc"],  cc: { type: ["string", "null"] }

Without the second half the parameter is silently promoted to mandatory. Under strict: true the model then has no way to leave it out; without strict, required is still what it is told the tool wants. Keys that were genuinely required are left alone.

When the model takes up that offer and sends cc: null, the tool reads it as cc left out: a null at a key your schema does not require, and does not allow to be null, is removed before your validator runs. A field you declared .nullable() keeps its null; a null at a required key is still an error. The reading comes from the rule's own record of the nodes it widened, read off the schema that rule returned (a snapshot taken before any later rule runs), so it holds inside unions (a z.discriminatedUnion, a z.union of objects, arrays of either), for a rule of your own that records through ctx.nullMeansAbsent, and whatever the rules after it do — the gemini rule on an OpenAI-compatible Gemini endpoint, or a rule of yours that rebuilds or clones nodes.

An object you declared open (z.record, .catchall(), z.looseObject) stays open; every other object gets additionalProperties: false. OpenAI accepts an open object on any tool that does not set strict: true. Under strict: true OpenAI refuses one, so the rule throws a ToolSchemaError before the model is called: declare the keys with z.object, or drop strict from the tool.

An enum gets null added to its values too, and a const is wrapped in anyOf rather than widened in place — in both cases changing only type would leave a node whose type admits null while its value constraint forbids it, which nothing can satisfy.

License

Apache-2.0 — see LICENSE.

Description from the npm listing.

  • ai
  • agent
  • llm
  • typescript
  • ai-sdk
  • durable
  • exactly-once
  • json-schema
  • provider-compatibility

README badge

Show your rank in a README or on your website. The badge updates automatically.

Charts

Images: 30d · 1y · all time · 1600×900 dark

Adoption over time

@gnldev/tool-schema weekly downloads on npm, last 90 days: 378 weekly downloads as of Oct 18, 2026.@gnldev/tool-schemaWeekly downloads on npm · Last 90 days378downloads / week340360380400420Jul 20Aug 4Aug 19Sep 3Sep 18Oct 3Oct 18downloads / weekOct 18, 2026 – Oct 18, 2026 · 1 observations · Updated Oct 18, 2026pluginstats.com
@gnldev/tool-schema weekly downloads on npm, last 90 days: 378 weekly downloads as of Oct 18, 2026.

7/30/90-day growth

@gnldev/tool-schema weekly downloads growth on npm: 7-day growth unavailable, 30-day growth unavailable, 90-day growth unavailable.@gnldev/tool-schemaWeekly downloads growth on npm378downloads / week now7-day growthinsufficient historyInsufficient history30-day growthinsufficient historyInsufficient history90-day growthinsufficient historyInsufficient historyGrowth vs. nearest observation to each baseline date · Updated Oct 18, 2026pluginstats.com
@gnldev/tool-schema weekly downloads growth on npm: 7-day growth unavailable, 30-day growth unavailable, 90-day growth unavailable.

Ranking history

@gnldev/tool-schema npm ranking history: currently #1593 (by weekly downloads).@gnldev/tool-schemanpm ranking · by weekly downloads · Last 90 days#1593current rank#1591#1592#1593#1594#1595Jul 22Aug 6Aug 21Sep 5Sep 20Oct 5Oct 20rankOct 20, 2026 – Oct 20, 2026 · 1 observations · Updated Oct 18, 2026pluginstats.com
@gnldev/tool-schema npm ranking history: currently #1593 (by weekly downloads).

Listing placement

All npm2,320 listings · 116 pages · 1,161 shown · page 80, #17 (overall #1,597)
All npm: every listing in weekly downloads order

Listing placement

AI SDKs259 listings · 13 pages · page 10, #14 (overall #194)
AI SDKs: every listing in weekly downloads order

Filled points are observed values; hollow points come from Internet Archive snapshots of the listing page. Dashed segments span periods with no observations — values between points are not interpolated.

Each band is one page of 20. Weekly downloads on a linear scale. Placement is projected from weekly downloads, so it can differ from the marketplace's own sort order. Hover a dot to see the listing.

Recent observations

Full history (1)
Recent weekly downloads observations for @gnldev/tool-schema
Date (UTC)Weekly downloadsChange vs. previous
378—

Similar npm AI SDKs plugins

All 20 @gnldev/tool-schema alternatives

Data source

Weekly downloads (trailing 7 complete days) come from the official npm downloads API. Downloads include CI and mirrors and are not equivalent to installs or users. npm publishes no ratings.

Listing: https://www.npmjs.com/package/@gnldev/tool-schema. First seen Oct 20, 2026; last successful collection Oct 20, 2026. See the methodology.