Skip to content

pascalorg/lingo

Repository files navigation

lingo

Make forms easier, LLM tools safer.

People type fast and loose: 180cm, 5ft 11, 1.5 cups, 90 min, next friday, 1,5 kg, typos included. Models emit fluent, over-formatted strings: "5'11\"", "1½ cups", "twenty-five kg", "3pm EST", "1,234 kg". Your database wants canonical values: one number in one unit, one ISO date. The library is the layer in between: natural-language quantities, units, dates, and ranges parsed into validated values, then humanized back. Zero dependencies; English-first parsing with locale-aware formatting (locale packs are on the roadmap, plan 013).

For the web. Use one text field instead of a value box plus a unit dropdown:

  • Accepts how people actually type: 180cm, 5ft 11, 2 lb 3 oz, an hour and a half, typos with did-you-mean (5 meterz), and fuzzy words (it's hot) where a field opts in.
  • Validation UX ships as data: fields are never yelled at mid-typing (2 f is incomplete, not invalid), and every issue carries a stable code, a human message you can override, a span into the original input, and did-you-mean suggestions.
  • No silent guesses: ambiguous input (1,234: 1.234 or 1234?) returns a deterministic best reading plus ranked alternatives and a warning; confirm strictness turns each assumption into a one-click confirmation.
  • Two-way and tested: whatever format()/humanize*() emits re-parses to the same value. 1.9999 m formats as 6′7″, never 5′12″.
  • Headless DOM controller, <lingo-input> element, and React hook. No styles shipped, no framework lock-in, and parsing is microsecond-scale, fast enough to run on every keystroke.

For LLMs. Models are better at emitting "5'11\"" than 1.8034; the /ai fields make the string the reliable path:

  • Standard Schema fields (quantityField, dateField, lingoObject) drop into AI SDK tools, OpenAI/Anthropic/Gemini strict modes, LangChain, and MCP (lingoTool()). One field definition covers the provider wiring documented in the recipes.
  • Tool-boundary defaults reject risky values: ambiguous numbers, ignored timezones, and clock-drifting relative dates fail loudly with [CODE] ... Did you mean ...? messages a model can self-correct from in one round trip.
  • Measured on a 160-fixture recorded canonicalization corpus (not an LLM benchmark): naive Number()/new Date() coercion accepts 17.5% of it and is silently wrong on 6.3%; lingo accepts 96.9% with zero silent-wrongs.
  • Deterministic and replayable: pass an explicit now and results are exactly reproducible. The /ai date field requires it for relative dates, so a queued or retried tool call never drifts across midnight.
  • repairToolCallWith/canonicalizeValues fix malformed payloads client-side, with no extra model call.

One parser powers both sides. The same lingoObject can validate a model tool call and a human form through Standard-Schema form resolvers (React Hook Form, TanStack Form, ...).

This is the monorepo. The library README with install, API tour, and recipes lives with the package: packages/lingo.

Layout

Path What it is
packages/lingo @pascal-app/lingo, the published library (src, tests, bench, size/corpus/zero-deps gates)
apps/site Docs site with live parser demos (Next.js, port 3000 or next free)
plans/ Forward-looking specs, one numbered living markdown file per topic
wiki/ As-built docs: architecture, decisions, conventions, credits, research
AGENTS.md Canonical agent guide (hard rules, workflow, module map)
CONTEXT.md Vocabulary glossary with canonical names and synonyms to avoid

Quick start

bun install
bun run check     # typecheck + tests + build + size budgets + corpus gate + zero-deps gate

Develop (library + site together):

bun dev           # tsup --watch on the library + site dev (port 3000, auto-increments)
bun kill          # stop all lingo dev processes (ports 3000-3003 + this repo's watchers)
bun restart       # kill + clear .next*/.turbo caches + bun dev

The site consumes the library as a live workspace link, so watch rebuilds show up in the running site. (cd apps/site && bun dev still works for site-only work; bun run site:sync refreshes served data files like llms.txt.)

Contributing

See CONTRIBUTING.md. The short version: bun run check must be green, zero runtime dependencies is non-negotiable, specs in plans/ are living documents, and notable changes land in the CHANGELOG under [Unreleased].

License

MIT

About

Make forms easier, LLM tools safer. Natural-language quantities, units, dates & ranges parsed into canonical values — zero dependencies, two-way.

Topics

Resources

License

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors