import { Schema, type Effect } from "effect" import type { LLMError, LLMEvent, LLMRequest, ProtocolID } from "../schema" /** * The semantic API contract of one model server family. * * A `Protocol` owns the parts of a route that are intrinsic to "what does * this API look like": how a common `LLMRequest` becomes a provider-native * body, what schema that body must satisfy before it is JSON-encoded, and * how the streaming response decodes back into common `LLMEvent`s. * * Examples: * * - `OpenAIChat.protocol` — chat completions style * - `OpenAIResponses.protocol` — responses API * - `AnthropicMessages.protocol` — messages API with content blocks * - `Gemini.protocol` — generateContent * - `BedrockConverse.protocol` — Converse with binary event-stream framing * * A `Protocol` is **not** a deployment. It does not know which URL, which * headers, or which auth scheme to use. Those are deployment concerns owned * by `Route.make(...)` along with the chosen `Endpoint`, `Auth`, * and `Framing`. This separation is what lets DeepSeek, TogetherAI, Cerebras, * etc. all reuse `OpenAIChat.protocol` without forking 300 lines per provider. * * The four type parameters reflect the pipeline: * * - `Body` — provider-native request body candidate. `Route.make(...)` * validates and JSON-encodes it with `body.schema`. * - `Frame` — one unit of the framed response stream. SSE: a JSON data * string. AWS event stream: a parsed binary frame. * - `Event` — schema-decoded provider event produced from one frame. * - `State` — accumulator threaded through `stream.step` to translate event * sequences into `LLMEvent` sequences. */ export interface Protocol
{ /** Stable id for the wire protocol implementation. */ readonly id: ProtocolID /** Request side: schema for the provider-native body and how to build it. */ readonly body: ProtocolBody /** Response side: streaming state machine. */ readonly stream: ProtocolStream } export interface ProtocolBody { /** Schema for the validated provider-native body sent as the JSON request. */ readonly schema: Schema.Codec /** Build the provider-native body from a common `LLMRequest`. */ readonly from: (request: LLMRequest) => Effect.Effect } export interface ProtocolStream { /** Schema for one decoded streaming event, decoded from a transport frame. */ readonly event: Schema.Codec