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;