Files
codex/codex-rs/agent-message-board-client/src/protocol.rs
T
felixxia-oai a47d1338c1 Extract shared message-board code into codex-message-board (#55970)
## What changed

Move the message-board API, types, permissions, storage backends, and tool implementations into the new `codex-message-board` crate. Keep extension registration in `codex-agent-message-board-extension`, and update core and the remote client to use the shared crate directly.

Move the existing board tests with the implementation and add the crate to the Cargo workspace and Bazel build.

GitOrigin-RevId: 33ce527c2bef7f862eba55cb9b32222902ccf4ad
2026-10-21 19:34:51 +00:00

108 lines
3.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Versioned service requests reuse board operations; only host identity travels separately.
use chrono::DateTime;
use chrono::Utc;
use codex_message_board::ChannelQuery;
use codex_message_board::CreateChannelRequest;
use codex_message_board::PostPreview;
use codex_message_board::PostQuery;
use codex_message_board::PostRequest;
use codex_message_board::ReadPostRequest;
use codex_message_board::ReadThreadRequest;
use codex_message_board::SubscriptionRequest;
use codex_message_board::ThreadQuery;
use codex_protocol::AgentPath;
use codex_protocol::ThreadId;
use serde::Deserialize;
use serde::Deserializer;
use serde::Serialize;
use std::collections::HashMap;
use std::fmt;
pub(crate) const MAX_BODY: usize = 512 * 1024;
pub(crate) const MAX_RESPONSE: usize = 1024 * 1024;
/// A host credential. Debug output must never reveal its contents.
#[derive(Clone, Serialize)]
#[serde(transparent)]
pub struct AccessToken(pub(crate) String);
impl AccessToken {
pub fn new(value: String) -> anyhow::Result<Self> {
anyhow::ensure!(
(32..=4096).contains(&value.len()),
"credentials must contain 32–4096 bytes"
);
anyhow::ensure!(
value.bytes().all(|b| b.is_ascii_graphic()),
"credential must be ASCII without whitespace"
);
Ok(Self(value))
}
}
impl<'de> Deserialize<'de> for AccessToken {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Self::new(String::deserialize(deserializer)?).map_err(serde::de::Error::custom)
}
}
impl fmt::Debug for AccessToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("AccessToken([REDACTED])")
}
}
#[derive(Serialize)]
pub(crate) struct Registration {
pub(crate) members: HashMap<ThreadId, AgentPath>,
}
#[derive(Serialize)]
pub(crate) struct Call {
pub(crate) caller: ThreadId,
pub(crate) timestamp: Option<DateTime<Utc>>,
#[serde(flatten)]
pub(crate) operation: Operation,
}
#[derive(Serialize)]
#[serde(tag = "method", content = "params", rename_all = "snake_case")]
pub(crate) enum Operation {
CreateChannel(CreateChannelRequest),
ListChannels(ChannelQuery),
Post(PostRequest),
ListThreads(ThreadQuery),
SearchPosts(PostQuery),
ReadThread(ReadThreadRequest),
ReadPost(ReadPostRequest),
SetSubscription(SubscriptionRequest),
}
#[derive(Serialize)]
pub(crate) struct Watch {
pub(crate) caller: ThreadId,
pub(crate) turn_id: String,
}
/// A best-effort preview bound to the receiving turn. Hosts must atomically check
/// `turn_id` when admitting it; a received preview must never start a new turn.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BoardNotification {
pub recipient: ThreadId,
pub turn_id: String,
pub post: PostPreview,
}
#[derive(Deserialize)]
pub(crate) struct Failure {
pub(crate) code: String,
pub(crate) message: String,
}
#[derive(Deserialize)]
pub(crate) struct PermissionDeniedDetails {
pub(crate) action: Option<String>,
pub(crate) resource: Option<String>,
}