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
}
OptionRequiredPurpose
urlYesYour server route, such as /api/editor-ai.
headersNoExtra headers to send with every request.
fetchNoYour 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:

StatusError code
401 or 403unauthorized
413context_too_large
429rate_limited
400, 415, or 422invalid_request
Any other failed responsetransport_error

Create the transport once, outside your component, so it is not rebuilt on every render. To build the server side, use createEmendAiHandler.

On this page