Skip to content

openagents_sdk::chats::wire

What the chat API sends and takes (/v1/threads, its messages, and its event stream), with the rules every client applies to it. Nothing here makes a request, so the desktop and phone apps (through [crate::chats]'s calls) and the website's GPUI chat (through the browser's fetch and EventSource) read the same values the same way.

Rows are read leniently: a field the service adds later is ignored, and one it leaves out, or sends as null, takes its default.

ItemWhat it does
BadEvent structAn event [`Event::read`] refused.
Change structThe body of `PATCH /v1/threads/{id}`: only what changes.
Content structOne part of a [`MessageRow`].
Event enumOne event of a turn's stream: message text, tool output, cards, the end, or an error.
FileRef structA file sent with a message.
Filing structWhether a chat is pinned and archived, as the service reports it after a change.
Frames structSplits a turn's event stream into the `data` of each event, as the bytes arrive.
MessageBody structThe body of `POST /v1/threads` and `POST /v1/threads/{id}/messages`.
MessageRow structOne message in `GET /v1/threads/{id}/messages`, which keeps every message and its position (`msg_{index}`).
Page structA page of `{data, next}`.
Refusal structA refused turn: its code, a message to show, and when to try again.
RefusalCode enumWhy the service refused or ended a turn.
Started struct`201 {id, answering}` from `POST /v1/threads`.
Stopped structThe service's answer to a stop request.
Thread structOne chat in `GET /v1/threads`, and the row of `GET /v1/threads/{id}`.
ThreadDetail struct`GET /v1/threads/{id}`: the row and its newest messages, empty ones left out.
ThreadList struct`GET /v1/threads`.
ThreadMessage structOne message in `GET /v1/threads/{id}`.
TooLarge structA stream that sent more than [`Frames::LIMIT`] without ending an event.
is_request_id fnWhether `id` is a request ID the service takes: a lowercase or uppercase hex UUID with its dashes.
message_ok fnWhether `text` may be sent: not blank, and at most [`MAX_MESSAGE_CHARS`].
title fn`title` trimmed, when it may name a chat: not blank, at most [`MAX_TITLE_CHARS`], and without control characters.
MAX_EVENT_INDEX constThe highest message index a turn's events may name.
MAX_MESSAGE_CHARS constThe longest message, in characters, a turn may send.
MAX_TITLE_CHARS constThe longest chat title, in characters.

BadEvent

pub struct BadEvent;

An event [Event::read] refused.

Change

pub struct Change {
    pub title: Option<String>,
    pub pinned: Option<bool>,
    pub archived: Option<bool>,
    pub project: Option<Option<String>>,
}

The body of PATCH /v1/threads/{id}: only what changes.

Content

pub struct Content {
    pub kind: String,
    pub text: String,
}

One part of a [MessageRow].

Event

pub enum Event {
    Text {
        request_id: String,
        index: usize,
        role: crate::MessageRole,
        text: String,
        replace: bool,
    },
    Tool {
        request_id: String,
        index: usize,
        role: crate::MessageRole,
        text: String,
        replace: bool,
    },
    Cards { request_id: String, cards: Value },
    Done { request_id: String, outcome: String, revision: u64 },
    Error { request_id: String, error: Refusal },
}

One event of a turn's stream: message text, tool output, cards, the end, or an error.

Event::request_id

pub fn request_id(&self) -> &str

The request this event belongs to.

Event::read

pub fn read(data: &str, request_id: &str) -> Result<Self, BadEvent>

Reads one event's data for the turn request_id. Refuses an event that isn't JSON, belongs to another turn, or names a message past [MAX_EVENT_INDEX].

Event::ends

pub fn ends(&self) -> bool

Whether the turn's stream ends after this event.

Event::card_list

pub fn card_list(&self) -> Vec<Value>

The cards a [Event::Cards] carries, each one card's object.

FileRef

pub struct FileRef {
    pub id: String,
    pub name: String,
    pub kind: String,
    pub size: u64,
}

A file sent with a message.

Filing

pub struct Filing {
    pub pinned: bool,
    pub archived: bool,
}

Whether a chat is pinned and archived, as the service reports it after a change.

Frames

pub struct Frames {}

Splits a turn's event stream into the data of each event, as the bytes arrive. The native client reads the response through it; a browser's EventSource does the same splitting itself.

Frames::push

pub fn push(&mut self, chunk: &[u8]) -> Result<(), TooLarge>

Adds bytes read from the stream. Refuses more than [Frames::LIMIT] unread.

Frames::next

pub fn next(&mut self) -> Result<Option<String>, BadEvent>

The next whole event's data lines, joined, or None until more bytes arrive. An event with no data (a comment or keepalive) is skipped.

MessageBody

pub struct MessageBody<'a> {
    pub request_id: &'a str,
    pub text: &'a str,
    pub project: Option<&'a str>,
}

The body of POST /v1/threads and POST /v1/threads/{id}/messages.

MessageRow

pub struct MessageRow {
    pub id: String,
    pub role: String,
    pub content: Vec<Content>,
}

One message in GET /v1/threads/{id}/messages, which keeps every message and its position (msg_{index}).

MessageRow::index

pub fn index(&self) -> Option<usize>

Its position in the chat.

MessageRow::text

pub fn text(&self) -> String

Its text parts, joined by line breaks.

Page

pub struct Page<T> {
    pub data: Vec<T>,
    pub next: Option<String>,
}

A page of {data, next}.

Refusal

pub struct Refusal {
    pub code: RefusalCode,
    pub message: String,
    pub retry_after_ms: Option<u64>,
}

A refused turn: its code, a message to show, and when to try again.

RefusalCode

pub enum RefusalCode {
    QuotaExhausted,
    RateLimited,
    Busy,
    Unavailable,
    Timeout,
    AccessLost,
    StreamTimeout,
    Other(String),
}

Why the service refused or ended a turn.

Started

pub struct Started {
    pub id: String,
    pub answering: bool,
}

201 {id, answering} from POST /v1/threads.

Stopped

pub struct Stopped {
    pub request_id: String,
    pub stopped: bool,
    pub finished: bool,
}

The service's answer to a stop request.

Thread

pub struct Thread {
    pub id: String,
    pub request_id: Option<String>,
    pub outcome: Option<String>,
    pub title: String,
    pub line: String,
    pub surface: String,
    pub computer: Option<String>,
    pub updated_unix: u64,
    pub working: bool,
    pub online: bool,
    pub can_reply: bool,
    pub pinned: bool,
    pub project: Option<String>,
    pub messages: usize,
}

One chat in GET /v1/threads, and the row of GET /v1/threads/{id}.

Thread::pending

pub fn pending(&self) -> bool

Whether an answer is being written now.

Thread::synced

pub fn synced(&self) -> bool

Whether the chat lives on a computer or phone rather than here.

ThreadDetail

pub struct ThreadDetail {
    pub thread: Thread,
    pub messages: Vec<ThreadMessage>,
    pub earlier: usize,
}

GET /v1/threads/{id}: the row and its newest messages, empty ones left out.

ThreadList

pub struct ThreadList {
    pub threads: Vec<Thread>,
    pub total: usize,
    pub more: bool,
    pub next_offset: Option<usize>,
}

GET /v1/threads.

ThreadMessage

pub struct ThreadMessage {
    pub role: String,
    pub text: String,
    pub files: Vec<FileRef>,
}

One message in GET /v1/threads/{id}.

TooLarge

pub struct TooLarge;

A stream that sent more than [Frames::LIMIT] without ending an event.

is_request_id

pub fn is_request_id(id: &str) -> bool

Whether id is a request ID the service takes: a lowercase or uppercase hex UUID with its dashes.

message_ok

pub fn message_ok(text: &str) -> bool

Whether text may be sent: not blank, and at most [MAX_MESSAGE_CHARS].

title

pub fn title(title: &str) -> Option<&str>

title trimmed, when it may name a chat: not blank, at most [MAX_TITLE_CHARS], and without control characters.

MAX_EVENT_INDEX

pub const MAX_EVENT_INDEX: usize = 4000;

The highest message index a turn's events may name.

MAX_MESSAGE_CHARS

pub const MAX_MESSAGE_CHARS: usize = 4000;

The longest message, in characters, a turn may send.

MAX_TITLE_CHARS

pub const MAX_TITLE_CHARS: usize = 120;

The longest chat title, in characters.