Custom Providers
A provider is any object with a complete(prompt) method. That is the entire interface, so a local model, an internal gateway or a proxy takes about ten lines.
The interface
const myAdapter = {
name: 'my-llm',
async complete(prompt, options = {}) {
// Call your model however you like and return its text response.
const res = await fetch('https://llm.internal/v1/complete', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ prompt, max_tokens: options.maxTokens ?? 4096 }),
})
const data = await res.json()
return data.text
},
}Using it
import { translateJSON } from '@shipi18n/core'
const { result } = await translateJSON({
content: source,
from: 'en',
to: 'de',
provider: myAdapter,
})What the engine expects back
- A string. Anything else is treated as an error.
- The prompt asks for JSON, and the engine parses it. If your model wraps output in a code fence, strip it in the adapter before returning.
- Throw on failure rather than returning an empty string — the engine falls back to per-string retries when a batch fails, and a thrown error is what triggers that.
Why this matters
Because the provider boundary is one method, nothing about Shipi18n ties you to a vendor. If a cheaper or better model appears next quarter, you swap the adapter and keep every other guarantee — structure preservation, placeholder validation and incremental translation are all provider-agnostic.