# kcode-openai-api Specification
## 1. Purpose and boundary
`kcode-openai-api` is a standalone Rust 2024 library imported by a larger
server. It owns direct OpenAI HTTP transport, fixed supported-model selection,
input validation, response normalization, credential lifetime, and bounded
response handling for the OpenAI API actions Kennedy needs.
It is not an HTTP server and defines no wire contract. The integrating server
owns secret retrieval, authentication, authorization, routes, serialization,
listener policy, cancellation, logging, persistence, and mapping Rust errors to
its own API.
The public client is `OpenAi`. `OpenAi::open(api_key)` returns the object whose
methods perform every direct OpenAI API action currently in Kennedy plus the
new image-generation action.
## 2. Supported provider surface
The compiled operations and model identifiers are:
- `OpenAi::transcribe` uses `POST /v1/audio/transcriptions` and
`gpt-4o-transcribe`;
- `OpenAi::generate_image` uses `POST /v1/images/generations` and
`gpt-image-2`;
- `OpenAi::edit_image` uses `POST /v1/images/edits` and `gpt-image-2`;
- `OpenAi::agent_turn` uses `POST /v1/responses` with a caller-selected exact
model and `store:false`; and
- `OpenAi::model_metadata` uses `GET /v1/models/{model}`.
Image operations do not accept arbitrary model identifiers. Agent turns accept
a locally validated exact model because provider selection and allow-list
policy belong to the intelligence router. Chat Completions, realtime audio,
speech generation, embeddings, moderation endpoints, file storage, image
variations, and stateful conversations are outside the current surface.
Calls are non-streaming and perform no automatic retry. The library returns
OpenAI's `x-request-id` when available so the caller can log and investigate a
specific request.
## 3. Audio transcription
`AudioInput` owns a safe ASCII basename, normalized MIME type, and in-memory
bytes. Inputs must be non-empty and no larger than 25 MiB. Accepted extensions
are flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, and webm. Accepted MIME values
cover the corresponding audio types plus MP4/WebM video containers and OGG
application content used by current browser recordings.
`TranscriptionRequest::new` supplies Kennedy's existing faithful-transcription
prompt. Callers may replace it with 1 through 32,000 characters or remove it,
and may supply an optional two-letter lowercase ISO-639-1 language. The method
sends JSON response format and accepts only a non-empty `text` result.
Usage is optional. Token-billed usage contains input, output, and total tokens
plus optional audio/text input detail. Duration-billed usage contains finite,
non-negative seconds. Unsupported or malformed usage in an otherwise
successful response is a protocol error rather than silently returning an
incorrect accounting value.
The library does not infer content type, transcode, split, persist, or stream
audio. It does not expose diarization, speaker samples, timestamps, log
probabilities, translations, or alternate models.
## 4. GPT Image 2 generation
`ImageGenerationRequest` contains a non-empty prompt of at most 32,000
characters, output dimensions or automatic sizing, automatic/low/medium/high
quality, PNG/JPEG/WebP format, optional JPEG/WebP compression, automatic or
opaque background, automatic or low moderation, and an optional end-user
identifier.
Every call explicitly requests `gpt-image-2`, one final image, non-streaming
output, and base64-backed GPT Image response behavior. The returned base64 is
decoded and must produce non-empty bytes. A single-image request returning zero
or multiple images is a protocol error.
Explicit dimensions must satisfy all compiled GPT Image 2 constraints: both
edges are multiples of 16, neither edge exceeds 3,840 pixels, the long edge is
at most three times the short edge, and total pixels are between 655,360 and
8,294,400 inclusive. Requests above 2,560 by 1,440 total-pixel class may use
provider behavior that OpenAI documents as experimental.
GPT Image 2 does not support transparent backgrounds, so the public type
exposes only automatic and opaque behavior. PNG rejects explicit compression;
JPEG and WebP accept 0 through 100 inclusive.
The response contains creation time, one `GeneratedImage`, optional provider
size and quality, optional typed token usage, and optional request ID.
`GeneratedImage::Debug` reports only format and byte count.
`ImageEditRequest` uses the same prompt and output controls and accepts 1
through 16 ordered images. Each image uses the validated in-memory
`ImageInput`; the first is the primary edit source and the rest are references.
It sends multipart `image[]` fields and returns exactly one final image.
Masks, multiple output images, partial-image streaming, and conversational
image generation are not included.
## 5. Stateless agent turns and model metadata
An agent turn contains exact text input, a safe exact model identifier,
provider-neutral reasoning effort, and zero or more named tools with JSON
Schema parameters. It returns assistant text, at most one normalized tool
call, response and model identifiers, and optional token usage. Tool results,
thread continuation, application policy, and the multi-round loop remain
outside this client.
Model metadata is a bounded authenticated read. The normalized result contains
the model identifier and provider-reported context or maximum-input limits when
present.
## 6. Credentials and network safety
Construction takes ownership of one API key, trims it, rejects empty or
invalid-header values, and retains no other credential. The temporary supplied
string and retained string use zeroizing storage. The key is shared across
clones, redacted from `Debug`, and never serialized, recorded, or placed in a
URL or request body.
For each request, the client builds a sensitive `Authorization: Bearer ...`
header. The HTTPS-only HTTP client uses only compiled OpenAI endpoints and is
built without environment proxy discovery, redirects, referrers, or automatic
retries. Credential-bearing `reqwest` and `zeroize` dependencies are
exact-version pinned and reviewed in `DependencyAudit.md`.
Zeroization is best-effort memory hygiene, not encryption: it overwrites the
owned key buffer when its final owner is dropped, but cannot retroactively
erase old reallocation buffers, compiler-created copies, or copies made inside
the HTTP and TLS stacks.
## 7. Response and error handling
Provider bodies are read incrementally and limited to 128 MiB regardless of a
declared content length. A successful response must be valid JSON and satisfy
the method-specific shape. The library does not return raw provider payloads.
Provider error bodies are reduced to a control-cleaned code of at most 100
characters, message of at most 400 characters, HTTP status, and optional
request ID. Transport errors are reduced to timeout or service-reachability
classes rather than exposing request internals.
The library deliberately performs no automatic retries. A billable operation
may have completed remotely before a timeout or connection failure becomes
visible locally, so retry policy belongs to the integrating application.
## 8. Storage, state, and concurrency
The crate opens no database and creates no files. It has no configuration,
environment discovery, save/load, usage ledger, spending limit, or recovery
API. It retains only the key, fixed endpoint URLs, and HTTP connection pool.
Clones may make requests concurrently through the shared connection pool. Each
request owns its prompt/media values until they are sent. Returned transcript
and generated-image values are owned by the caller. Dropping the last client
clone discards the retained key and connection pool.
## 9. Managed-library conformance
The root contains `Cargo.toml`, `Documentation.md`, ordinary UTF-8 source, a
literal canonical package version in `Cargo.toml`, and its own empty
`[workspace]` so it remains separate inside Kennedy's repository. No redundant
`Version.txt` is required. Generated build output, credentials, audio, images,
and other binary data are not part of the managed library.
The crate is validated independently with formatting, build, Clippy, tests,
documentation tests, and package inspection. It has no path dependency on
Kennedy and can be moved to a repository and published without source changes.