createFetchTransport
Send AI requests from the browser to your server route.
createFetchTransport sends each AI request from the browser to a URL on your
server, and reads the answer as it streams back. Pass the result to your AI
component as its transport prop.
import { createFetchTransport } from "@emend/ai/transport"
const transport = createFetchTransport({
url: "/api/editor-ai",
})Options
interface FetchTransportOptions {
readonly url: string
readonly headers?: HeadersInit
readonly fetch?: typeof fetch
}| Option | Required | Purpose |
|---|---|---|
url | Yes | Your server route, such as /api/editor-ai. |
headers | No | Extra headers to send with every request. |
fetch | No | Your own fetch function, for example to add cookies or logging. |
The transport always sends Accept: text/event-stream and
Content-Type: application/json. You cannot override these two headers.
Send a sign-in token
const transport = createFetchTransport({
url: "/api/editor-ai",
headers: {
Authorization: `Bearer ${token}`,
},
})If the token changes between requests, or your route is on a different
domain, pass your own fetch instead:
const fetchWithCredentials: typeof fetch = (input, init) =>
fetch(input, { ...init, credentials: "include" })
const transport = createFetchTransport({
url: "https://api.example.com/editor-ai",
fetch: fetchWithCredentials,
})If the route is on a different domain, your server must also send the right CORS headers.
What the server must send back
The server streams the answer as Server-Sent Events (SSE). Each event is JSON
in one of these shapes. text-delta is a piece of the answer, done means the
answer is finished, and error means something went wrong.
type EmendStreamEvent =
| { protocolVersion: 1; type: "text-delta"; requestId: string; delta: string }
| { protocolVersion: 1; type: "done"; requestId: string }
| {
protocolVersion: 1
type: "error"
requestId: string
error: EmendAiError
}Events must come in order and match the request ID. If the response is empty,
has broken JSON, has an unknown event, or ends without done, you get a
transport_error.
HTTP errors
If the server returns an emend error, the transport passes it on. Otherwise it turns the HTTP status into an error code:
| Status | Error code |
|---|---|
401 or 403 | unauthorized |
413 | context_too_large |
429 | rate_limited |
400, 415, or 422 | invalid_request |
| Any other failed response | transport_error |
Create the transport once, outside your component, so it is not rebuilt on
every render. To build the server side, use
createEmendAiHandler.