Skip to main content

Crate nanocodex_oai_api

Crate nanocodex_oai_api 

Source
Expand description

§Nanocodex OpenAI API

Tower-native building blocks for the OpenAI Responses API.

nanocodex-oai-api is useful without the Nanocodex agent loop. It owns the typed request and response model, persistent Responses transport, replayable Tower attempt boundary, and batteries-included conversation state.

§Quick start

Pass an OpenAI Platform API key to OpenAi::new. Developer instructions create the stable boundary of a client-owned Session, and follow-on calls retain completed history automatically:

use nanocodex_oai_api::OpenAi;

let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?;
let mut session = openai
    .instructions(
        "Remember user-provided deployment facts and say when information is missing.",
    )
    .build()?;

let mut turn = session.turn();
let completed = turn
    .create("The production deployment region is us-west-2.")
    .await?;

println!("{}", completed.output_text());
if let Some(cost) = completed.estimated_cost() {
    println!("estimated {}", cost.amount());
}

This crate supports gpt-5.6-sol (the default), gpt-5.6-terra, and gpt-5.6-luna. Select a client default with OpenAi::builder(auth).model(Model::Terra). A session keeps that model for its lifetime, and each replayable attempt retains it across retries. Changing models would invalidate the provider checkpoint and require an inefficient replay of the complete retained context.

API-key HTTPS OpenAI routing gateways may qualify those same closed model identifiers with OpenAi::builder(auth).model_id_prefix("openai"). The prefix changes only the wire model ID; model-specific reasoning, compaction, pricing, and snapshots continue to use the typed Model value. It does not add an alternate provider or arbitrary-model surface.

USD estimates require no pricing configuration. Each model applies its published standard rates, or its priority rates when OpenAiBuilder::fast_mode is enabled. Terra and Luna usage receive the same complete estimate and status treatment as Sol. Provider-omitted usage remains distinguishable as usage_not_reported.

§ChatGPT subscription login

Available on native targets. The login and managed credential store are marked as such in docs.rs and are not compiled for WebAssembly.

auth::ChatGptLogin performs an authorization-code login with PKCE using a loopback callback. The caller chooses the credential file, presents the authorization URL, and waits for the browser callback. Successful completion atomically writes the credential file.

The same file can then be loaded into a managed OpenAi client:

use std::path::PathBuf;

use nanocodex_oai_api::{
    OpenAi,
    auth::{ChatGptLogin, load_chatgpt_auth},
};

let auth_file = PathBuf::from(std::env::var("NANOCODEX_AUTH_FILE")?);

let login = ChatGptLogin::start(&auth_file).await?;
println!("Open this URL to sign in:\n\n{}", login.authorization_url());
let account = login.complete().await?;
println!("Signed in to ChatGPT account {}", account.account_id);

let auth = load_chatgpt_auth(&auth_file)?;
let openai = OpenAi::new(auth)?;
let mut session = openai
    .instructions(
        "Answer concisely. Preserve identifiers exactly and say when information is missing.",
    )
    .build()?;

let completed = session
    .turn()
    .create("Explain what deployment identifier deploy_01J8Y7Q2 refers to.")
    .await?;
println!("{}", completed.output_text());

Keep the credential file outside source control and reuse the same path on later runs. It uses Codex’s auth.json format, so Codex and multiple Nanocodex processes can safely share the same path. auth::load_chatgpt_auth adopts a same-account rotation from disk before refreshing, refreshes expiring credentials, and recovers an unauthorized request once with the refreshed authorization. auth::chatgpt_auth_status inspects the selected account without exposing tokens, and auth::logout_chatgpt removes the stored credentials.

A Response is also a typed stream. It retains the completed aggregate after the stream reaches ResponseEvent::Completed:

use futures_util::TryStreamExt;
use nanocodex_oai_api::{OpenAi, ResponseEvent};

let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?;
let mut session = openai
    .instructions("Answer concisely and preserve exact identifiers.")
    .build()?;
let mut turn = session.turn();
let mut response = turn.create("Explain the identifier req_7f3.");

while let Some(event) = response.try_next().await? {
    if let ResponseEvent::OutputTextDelta(delta) = event {
        print!("{delta}");
    }
}

let completed = response.await?;
assert!(!completed.output_text().is_empty());

§GPT Realtime voice

Available on native targets with the realtime feature.

OpenAi::realtime opens an independent GPT Realtime conversation using the same credential and API base. Platform API keys use a direct Realtime WebSocket. Managed ChatGPT credentials create the media call through the ChatGPT backend and join its sideband control WebSocket with the same bearer and account identity. When no host attestation is available, Nanocodex sends the same unavailable-token envelope Codex uses when attestation generation times out; hosts that own an attestation integration may override it with realtime::RealtimeSessionBuilder::attestation_header. The library accepts and emits signed 16-bit little-endian, 24 kHz mono PCM through a cheap realtime::RealtimeSession handle and an independent realtime::RealtimeEvents stream. It does not open audio devices, so callers can connect a microphone, files, or ordinary stdin and stdout pipes. The experimental nanocodex-voice crate packages default desktop devices and background-agent delegation without moving those policies into this transport boundary.

Both transports expose background-agent delegation as realtime::RealtimeEvent::AgentRequest. An embedding handles that event with its existing agent or tool loop, then calls realtime::RealtimeSession::complete_agent_request with the typed result. The nanocodex Ratatui consumer is one concrete desktop adapter: on macOS and Windows, /voice connects the default microphone and speaker while preserving the coding agent’s normal history and lifecycle. /voice list prints the available voice names, /voice cove starts a named voice, and /voice off stops it. Managed ChatGPT sessions use Codex’s current voice set and default to cove; Platform sessions default to marin. The TUI uses either the coding session’s ChatGPT subscription credential or its Platform API key directly; no second credential is required. Other native hosts can use the device-neutral realtime-pipe example with their audio stack.

§Ownership and replay

A session owns authoritative typed history and one concrete Tower service. A ResponseTurn marks a logical agent turn and keeps WebSocket turn-scoped state stable across sequential create and compact calls. Only completed operations commit. Healthy calls send a delta plus a private continuation ID; reconnects replay complete committed history.

The higher-level nanocodex-agent crate decides when to compact and how to execute tools. This crate implements the provider operation and atomic history replacement without embedding agent policy.

§Attempt accounting

Transport metrics distinguish physical Responses attempts from retries. A sent attempt that is cancelled or fails before a provider terminal event increments billing_uncertain_response_attempts; its ModelAttemptFailed event also sets billing_uncertain. This does not assume that the provider charged the request. It records that observed token usage is only a lower bound, while completed and provider-rejected responses remain exact.

§Contract-only builds

The default client feature remains the complete OpenAI boundary, including authentication, managed sessions, Tower services, transports, telemetry, and pricing. Process companions that only need the dependency-light prompt, response-item, and tool wire contracts may disable default features. This keeps one canonical contract without linking an unused network client; it does not create an alternate provider or transport implementation.

§Tools and managed sessions

The tools module defines the model-visible tool contract shared with nanocodex-tools. A standalone Session does not run a tool loop or attach a nanocodex-tools::Tools registry automatically. Use nanocodex-agent for that batteries-included composition. Consumers implementing their own loop can install definitions with SessionBuilder::tool_definitions and return paired tool outputs with session::ResponseInput::items.

tools::ToolDefinition::namespace represents the provider-native Responses namespace shape for related function tools. Function output schemas remain client-owned execution metadata: they are available through tools::ToolDefinition::output_schema for Code Mode declarations but are not serialized into the provider’s function declaration.

§Going lower level

The crate root keeps the normal conversation path and shared input policy prominent: OpenAi, Session, ResponseTurn, Response, CompletedResponse, Prompt, Thinking, and their errors.

  • session adds typed multimodal input, session identity, and explicit compaction results.
  • responses contains the complete typed OpenAI Responses protocol.
  • tools defines the shared tool contract; nanocodex-tools supplies the batteries-included runtime and implementations.
  • auth owns API-key credentials plus native managed ChatGPT login, persistence, refresh, and logout.
  • pricing and events expose automatic model-specific cost estimates and lifecycle-event components.
  • realtime exposes native GPT Realtime PCM streams and typed voice events.
  • tower contains the generic attempt, response, and retry contracts.
  • transport contains WebSocket/HTTPS selection, replay policy, transport failures, and connection statistics.

§Custom Tower stacks

OpenAiBuilder::layer wraps each session’s concrete service without boxing it. OpenAiBuilder::service installs a fresh caller-defined Service<tower::ResponsesAttempt> and is useful for custom transports, deterministic tests, and controlled replay. The standard stack owns its retry and reconnect policy; caller middleware should add deadlines, concurrency control, tracing, metrics, or error mapping rather than a second retry loop. Managed sessions own attempt construction and mutable transport state; callers do not construct the standard service or transport requests directly.

Both methods change the builder’s inferred concrete service-factory type. Ordinary inline call chains need no type annotation. Application wrappers can name or bound the generic result through tower::CallerServiceFactory, tower::LayeredServiceFactory, and tower::ResponsesServiceFactory without boxing the service stack.

Re-exports§

pub use responses::ResponseEvent;
pub use session::CompletedResponse;client
pub use session::Response;client
pub use session::ResponseError;client
pub use session::ResponseErrorKind;client
pub use session::ResponseTurn;client
pub use session::Session;client
pub use session::SessionBuildError;client
pub use session::SessionBuilder;client

Modules§

authclient
Authentication sources and managed credential snapshots.
eventsclient
Complete typed lifecycle events emitted around Responses operations. Complete typed lifecycle events emitted around Responses operations.
pricingclient
Automatic model-specific USD estimates from provider token usage. Built-in USD estimates for supported GPT-5.6 models.
realtimerealtime and non-target_family=wasm
Bidirectional GPT Realtime audio sessions and typed conversation events. GPT Realtime WebSocket sessions.
responses
Complete typed request, event, and item model for the Responses protocol. Typed request, event, and item model for the Responses protocol.
sessionclient
Managed session identities, inputs, and compaction results.
tools
Tool contracts shared by agent loops and concrete tool runtimes. Dependency-light contract for caller-defined and runtime-provided tools.
towerclient
Generic Tower attempt, service, retry, and streamed-output contracts. Generic Tower attempt, retry, and completed streamed-output contracts.
transportclient
Responses transport policy, errors, and connection statistics. Responses transport policy, errors, and connection statistics.

Structs§

OpenAiclient
Configured, cloneable OpenAI client recipe.
OpenAiBuilderclient
Builder for a configured OpenAI client and concrete Tower service factory.
Prompt
User input for one agent turn.
PromptMessage
One text-only message in a synthetic prompt transcript.

Enums§

ImageDetail
Image fidelity requested from the model.
Model
Supported models in the GPT-5.6 coding-model family.
OpenAiErrorclient
Invalid OpenAI client configuration.
PromptInput
Ordered input for one agent turn.
PromptMessageRole
Role of one message in a synthetic prompt transcript.
PromptValidationError
Invalid model-visible prompt content.
ReasoningMode
Responses reasoning execution mode for the supported GPT-5.6 model family.
Thinking
Requested model reasoning effort.
UserInput
One ordered user-supplied prompt item.

Constants§

CONTEXT_WINDOW_TOKENS
Prompt-token budget used by automatic compaction to avoid long-context pricing.
MODEL
The default Responses model used by this SDK.