Request normalization engine for multi-provider inference workloads.
Project details
Checks
Built with
BabySea open source projects are organized into three categories:
| Category | Description |
|---|---|
| SDK | Typed developer entry points for creating, tracking, and managing BabySea workloads from application code. |
| Primitive | Reusable infrastructure boundaries extracted from BabySea's execution control plane. Each primitive focuses on one system concern. |
| Starter | Deployable reference applications that combine product UI, auth, storage, and BabySea execution patterns. Some starters may also include billing. |
BabySea OSS projects are published into three status levels:
| Status | Description |
|---|---|
| Working | Fully implemented and deployable. All documented capabilities function as described. Suitable for personal and small-team use. No breaking-change guarantees between versions. |
| Production | Working plus a hardened public runtime contract. Validated against a stated infrastructure stack with deterministic behavior, explicit failure modes, and a documented upgrade path. |
| Alpha | Early-stage implementation. Core structure exists but some capabilities may be incomplete, undocumented, or subject to breaking changes. Not recommended for production deployments. |
See CHANGELOG.md to track releases and public contract changes.
- Overview
- Stack contract
- Terminology
- Boundaries
- Architecture
- Quick start
- Core capabilities
- Version surface
- Security and Compliance
- Community
- License
rosetta-bridge is a request normalization primitive for teams integrating multiple media providers behind one product API. It validates a strict public request shape, applies declared defaults, and converts the normalized request into provider-native payloads at dispatch time.
The public package is intentionally scoped to TypeScript adapters and JSON Schema contracts. Auth, billing, persistence, queues, provider clients, webhooks, credit settlement, and routing intelligence stay in your application.
Provider APIs drift. rosetta-bridge gives you one stable request_* schema and keeps provider-native field names inside adapters, so a fallback provider cannot silently change request semantics after validation.
The primitive mirrors BabySea's production schema-hardening boundary: provider contracts are represented outside the customer request, strict public fields are validated with unknown-field rejection, defaults are declared in one place, canonical input can be persisted by the host after validation, and provider-native payloads are emitted through explicit mappers.
Public OSS behavior is limited to the TypeScript + JSON boundary implemented here: field specs, strict normalization, defaults, capability intersections, provider-order sentinels, prompt-enhancement helpers, moderation helpers, pricing-sensitive core fields, URL validation, canonical envelopes, and provider adapters. Hosted routes, private catalogs, credentials, provider SDK calls, queues, billing, telemetry, and Databricks routing are out of scope.
Define a public bridge manifest, keep provider-specific mapping inside adapters, cover the manifest with fixtures, and call normalize()/toProviderInput() before enqueueing or dispatching. You bring your backend, provider clients, database, billing, and runtime. The bridge handles schema safety.
| Layer | Required stack | Runtime responsibility |
|---|---|---|
| Provider contract | Provider docs, OpenAPI, JSON Schema, or typed notes | Record the external provider shape and intentional exclusions outside the public request. |
| Public request schema | rosetta-bridge field specs |
Validate input, apply defaults, reject unknown fields, and keep provider-only names out of customer APIs. |
| Provider adapter | TypeScript mapper functions | Convert normalized request fields into one provider-native payload. |
| Public contract | JSON Schema Draft 2020-12 | Version bridge manifests and normalization-result envelopes for docs, SDKs, and tests. |
| Integration boundary | Your backend, database, billing, queues, and SDKs | Own auth, persistence, rate limits, provider calls, webhooks, and dispatch outside the bridge. |
No hosted gateway, provider execution, queue worker, billing system, or routing service is part of this version contract.
| Term | Meaning in this package |
|---|---|
| Core field | Provider-agnostic request field such as request_prompt, request_aspect_ratio, request_output_format, or request_duration_seconds. |
| Option field | Public tuning field such as request_seed, request_negative_prompt, request_enhance_prompt, or request_guidance_scale. |
| Provider field | Provider-native API field. Provider names stay inside adapters, not in the public request schema. |
| Provider adapter | Converter with mapCore, mapOptions, and optional mapStructured functions. |
| Structured adapter | Explicit exception for providers whose payload must be assembled as nested objects or arrays. |
| Provider-order sentinel | request_provider_order: 'fastest' expands to the bridge's default provider order; the host application still chooses the active provider before dispatch. |
| Intersection | The safe overlap of capabilities across active providers: ratios, formats, input limits, duration, resolution, audio, and other pricing dimensions. |
- Not a hosted inference gateway or provider router.
- Not BabySea's private model catalog, provider configuration, credentials, or routing code.
- Not a replacement for authorization, billing, rate limiting, persistence, queues, or webhooks.
- Not a code generator for every provider API.
- Not a runtime guarantee that providers keep their public APIs stable; adapter fixtures must cover the contract you depend on.
Customer request
|
v
RosettaBridge.normalize()
| strict validation + declared defaults
v
Canonical request envelope
|- mapCore(...) common provider fields
|- mapOptions(...) optional public tuning fields
`- mapStructured(...) explicit nested-payload exception
|
v
Provider-native payload
|
v
Your provider SDK / route handler
For the full design, see docs/architecture.md and docs/normalization-rules.md. Fixture examples live in examples/fixtures/.
git clone https://github.com/babysea-community/rosetta-bridge
cd rosetta-bridge/client/typescript
npm install
npm run build
cd /path/to/your-app
npm install /path/to/rosetta-bridge/client/typescriptRuntime targets Node.js 22+. Local development and tests use the Vitest/Vite toolchain and require Node.js 22.12+.
import { RosettaBridge, sharedMediaFields } from 'rosetta-bridge';
const bridge = new RosettaBridge({
schemaVersion: 'bridge-definition.v1',
modelId: 'example/media-model',
supportedProviders: ['provider_a', 'provider_b'],
providerOrder: ['provider_a', 'provider_b'],
fields: {
core: sharedMediaFields({
supportedAspectRatios: ['1:1', '16:9'],
supportedFormats: ['png', 'jpg'],
defaultAspectRatio: '1:1',
defaultFormat: 'png',
providerOrders: ['fastest', 'provider_a,provider_b', 'provider_b,provider_a'],
defaultProviderOrder: 'fastest',
}),
options: {
request_detail_level: {
type: 'enum',
values: ['standard', 'high'],
default: 'standard',
},
request_seed: { type: 'integer' },
},
},
providers: {
provider_a: {
mapCore: (input) => ({
prompt: input.request_prompt,
aspect_ratio: input.request_aspect_ratio,
format: input.request_output_format,
}),
mapOptions: (input) => ({
detail: input.request_detail_level,
seed: input.request_seed,
}),
},
provider_b: {
mapCore: (input) => ({
text: input.request_prompt,
aspect: input.request_aspect_ratio,
output_format:
input.request_output_format === 'jpg'
? 'jpeg'
: input.request_output_format,
}),
mapOptions: (input) => ({
detail: input.request_detail_level,
seed: input.request_seed,
}),
},
},
});const providerPayload = bridge.toProviderInput(
{
request_prompt: 'a glass sculpture on a bridge',
request_aspect_ratio: '16:9',
request_output_format: 'jpg',
request_seed: 123,
},
'provider_b',
);Provider adapters keep native names private. One provider can receive aspect_ratio, another can receive aspect, and the public request stays the same.
The package ships a CLI for portable contract checks and fixture smoke tests:
cd client/typescript
npm run build
node dist/cli.mjs validate ../../examples/fixtures/bridge-definition.valid.json \
../../examples/fixtures/request.valid-minimal.json
node dist/cli.mjs schema ../../examples/fixtures/bridge-definition.valid.json
node dist/cli.mjs map ../../examples/fixtures/bridge-definition.executable.mjs \
../../examples/fixtures/request.valid-provider-mapping.json \
--provider provider_bJSON bridge manifests can validate requests and emit request JSON Schema. Mapping requires an executable JavaScript bridge module because provider adapters are functions.
Provider integrations fail when equivalent request fields drift across vendors. rosetta-bridge makes that drift explicit at the adapter boundary and rejects unsafe input before dispatch.
| Problem | How rosetta-bridge solves it |
|---|---|
| Schema drift. | Expose one public request_* field and map it per provider. |
| Failover breaks semantics. | Author public capabilities from the provider intersection, not the union. |
| Mappers become unreadable. | Separate common fields in mapCore from tuning fields in mapOptions. |
| Nested payloads need exceptions. | Use mapStructured only when flat core/options mapping cannot express the provider payload. |
| Unknown fields sneak through. | Strict normalization rejects undeclared public fields before provider dispatch. |
| Provider defaults vary. | Public defaults live in field specs instead of being inherited silently from providers. |
One request can mean different things to different providers:
- Provider A accepts
jpg; Provider B requiresjpeg. - Provider A calls the field
aspect_ratio; Provider B calls itaspect. - Provider A enables safety by default; Provider B disables it by default.
- Provider A supports
16:9; the fallback provider only supports1:1.
Without a normalization boundary, failover can change semantics after validation. With rosetta-bridge, those differences are declared in field specs, enum mappings, intersection helpers, and adapter fixtures before any provider call happens.
- Record provider-native shape outside the public request.
- Expose one strict public
request_*schema. - Declare defaults in field specs, not inside provider adapters.
- Author capability intersections from every active fallback provider.
- Keep pricing-sensitive dimensions in core fields.
- Use structured mapping only for explicit nested-payload exceptions.
- Reject unknown fields, invalid URLs, unsupported enums, and out-of-bound numbers before dispatch.
- Version every breaking public-contract change as a new schema version.
| BabySea production rule | rosetta-bridge rule |
|---|---|
| Raw provider schema mirrors provider docs. | Keep provider-native fields in adapter code or integration notes. |
| Refined schema is strict and customer-facing. | normalize(...) rejects unknown fields and accepts only declared request_* fields. |
| Defaults live in the refined public schema. | Field specs own defaults; adapters do not inherit provider defaults silently. |
| Capability intersections protect failover. | Ratios, formats, input limits, duration, resolution, and audio must be safe for every registered provider. |
| Core pricing fields stay inspectable. | Duration, resolution, audio, and input assets remain core fields before billing or routing decisions. |
| Provider-specific tuning maps after core fields. | mapOptions(...) owns knobs such as seed, moderation, prompt enhancement, and negative prompt. |
rosetta-bridge does not bill customers, but it preserves the invariant that fields affecting cost must be visible before dispatch:
request_duration_secondsfor duration-priced models.request_resolutionfor resolution-priced models.request_audiofor audio/no-audio pricing modes.request_input_assetsfor models where input count or type affects cost.
Adapters may rename or type-convert those values, but the host application can inspect them before queues, provider SDK calls, or billing decisions.
| Failure | Behavior |
|---|---|
| Missing required field | Throws ValidationError before adapter execution. |
| Unknown public field | Throws ValidationError by default. |
| Unsupported enum or number value | Throws ValidationError. |
| Invalid URL in asset fields | Throws ValidationError. |
| Unsupported provider | Throws ValidationError. |
Adapter returns a top-level undefined value |
Omits that provider field while preserving false, 0, null, and empty values. |
Run the bridge before enqueueing or dispatch so downstream systems consume only validated canonical requests.
Current version surface:
- Strict public
request_*validation and declared defaults - TypeScript provider adapters with
mapCore,mapOptions, andmapStructured - Capability helpers for simple intersections and aspect-ratio ordering
- JSON Schemas for
bridge-definition.v1andnormalization-result.v1 - Fixture-driven examples for valid, defaulted, invalid, and provider-mapping cases
- TypeScript SDK with tests
- Architecture and normalization-rule documentation
Future provider clients, hosted routes, billing, queues, telemetry, and routing services stay outside the public contract unless implemented and validated as separate packages.
The project publishes its trust signals through public GitHub, GitLab, or other CI provider checks so contributors can inspect the actual CI configuration, jobs, and reports.
- BabySea: execution control plane for generative media.
Using rosetta-bridge? Open a PR to add yourself.
We welcome PRs, issues, and design discussion. See CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md.
Apache License 2.0. Use it, fork it, ship it.