Skip to main content

codeoid_protocol/
lib.rs

1//! Codeoid wire protocol — Rust port of `src/protocol/types.ts` from the daemon.
2//!
3//! This crate is pure data: no I/O, no async, no Tokio. It defines serde-
4//! compatible types for every message that flows between a Codeoid client and
5//! the daemon's WebSocket server.
6//!
7//! # Design notes
8//!
9//! * **Discriminated unions.** TypeScript uses `type: "foo"` and `kind: "bar"`
10//!   as discriminants. In Rust these map to `#[serde(tag = "type")]` and
11//!   `#[serde(tag = "kind")]` tagged enums.
12//! * **Forward compatibility.** The daemon's design explicitly says "frontends
13//!   ignore unknown kinds". We mirror that by using `#[serde(other)]` on a
14//!   trailing `Unknown` variant and `#[serde(flatten)]` on extensible metadata
15//!   maps. Adding new server-side message kinds never breaks an old Rust
16//!   client — they deserialize into [`DaemonMessage::Unknown`] and the TUI
17//!   logs + skips them.
18//! * **Tool state as full replacement.** [`ToolState`] is a tagged enum where
19//!   each phase carries its own shape. When a [`SessionMessageDelta`] arrives
20//!   with `tool_state_update`, replace the whole [`ToolInfo::state`] — do not
21//!   merge fields.
22//!
23//! # Versioning
24//!
25//! [`PROTOCOL_VERSION`] is compared against the `protocol_version` field the
26//! daemon sends on `auth.ok`. Mismatch is non-fatal (the daemon's additive
27//! changes keep old clients working), but the client warns the user so they
28//! can upgrade.
29
30#![deny(missing_debug_implementations)]
31#![warn(clippy::pedantic)]
32#![allow(clippy::module_name_repetitions)]
33
34pub mod client;
35pub mod daemon;
36pub mod message;
37pub mod session;
38pub mod tool;
39
40pub use client::{
41    Attachment, ClientMessage, SearchScope, SendPriority, SessionImportSource, SettingPatch,
42};
43pub use daemon::{
44    AuthOkMsg, ClaudeConfigAgent, ClaudeConfigHook, ClaudeConfigMcpServer, ClaudeConfigScope,
45    ClaudeConfigSkill, DaemonMessage, ErrorCode, McpServerStatus, ModelInfo, ProviderCommand,
46    SecretStatus, SessionExportCounts, SessionExportManifest, SessionExportMetaSlim,
47    SessionExportPayload, SessionExportWorkdir, SessionSearchHit, SessionSearchSnippet,
48    SessionUiRequestMsg, SettingError, SettingField, SettingOption, SettingState, SettingsGroup,
49    SettingsManifest, SettingsSnapshot, SettingsTab, UiRequestMethod, UiResolvedReason,
50};
51pub use message::{
52    ContentPart, IdentityType, MessageIdentity, MessageRole, SessionMessage, SessionMessageDelta,
53};
54pub use session::{
55    ForkedFrom, SessionInfo, SessionMode, SessionStatus, SessionUsage, SessionWorktree, Subagent,
56    TurnUsage,
57};
58pub use tool::{CancelReason, ConfirmedBy, ToolInfo, ToolPhase, ToolState};
59
60/// Wire protocol version this crate speaks.
61///
62/// Compared against [`AuthOkMsg::protocol_version`] on connect. Bump this
63/// alongside the daemon's `PROTOCOL_VERSION` on any breaking change.
64pub const PROTOCOL_VERSION: u32 = 1;