@remcostoeten/ai-core
v0.2.0
Published
Provider-neutral AI completion contracts, run lifecycle, and deterministic fake provider. Zero dependencies.
Readme
This package is the seam, not the integration. It defines what a completion
request is, validates one, runs it against a provider you supply, and
guarantees what comes back. Reaching a real vendor is a separate package,
@remcostoeten/ai-sdk,
so a browser bundle that imports this one pulls in nothing else.
- Zero dependencies, enforced by a test that bundles this package for the browser and fails if
ai,@ai-sdk/*,process.envor a Node built-in appears in the output buildRequestvalidates against UTF-8 byte budgets and returns a rejection as a value, never as a thrown exception- The runtime owns the guarantees: ids reserved before provider lookup, gapless delta sequences from zero, a 4 MiB accumulated ceiling it enforces rather than trusts, and exactly one terminal with nothing after it
consumeEventsandaccumulateturn a run into text and a typed outcome- A deterministic fake provider driven by a script, so a consumer's tests need no network and no key
- NDJSON helpers to carry events over a wire, bounded per line
- Cancellation is an
AbortSignal; a deadline that fires outranks it and reportstimeout, notcancelled
The same seam exists in Rust as ai-core. Both read specs/fixtures/ and run
the same eight fake scripts, so segmentation, terminal kind, error category and
usage are held identical across the two languages.
Reference is typescript-core.md, worked usage is examples.md, and the wire contract is contracts.md.
Install
npm install @remcostoeten/ai-coreUse
import { buildRequest, consumeEvents, createFakeProvider, createRuntime, successScript } from '@remcostoeten/ai-core'
const runtime = createRuntime({ providers: [createFakeProvider(successScript(['hel', 'lo']))] })
const built = buildRequest({
requestId: 'request-1',
providerId: 'fake',
modelId: 'model',
messages: [{ role: 'user', content: 'hello' }],
})
if (!built.ok) return reject(built.error.reason)
const started = runtime.stream(built.request)
if (!started.ok) return reject(started.error.reason)
const outcome = await consumeEvents(started.events)
// outcome.status === 'done', outcome.text === 'hello'Not implemented
Structured output, retries, key rotation, provider fallback or routing, run recording, model listing, and framework helpers for React, Hono, Next.js or Tauri. Each is absent deliberately and recorded in the decision records.
xxx, Remco Stoeten MIT
