diff options
| author | soryu <soryu@soryu.co> | 2026-01-11 05:52:14 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-01-15 00:21:16 +0000 |
| commit | 87044a747b47bd83249d61a45842c7f7b2eae56d (patch) | |
| tree | ef2000ce79ffcc2723ef841acef5aa1deb1d5378 /makima/src/daemon/process/claude_protocol.rs | |
| parent | 077820c4167c168072d217a1b01df840463a12a8 (diff) | |
| download | soryu-87044a747b47bd83249d61a45842c7f7b2eae56d.tar.gz soryu-87044a747b47bd83249d61a45842c7f7b2eae56d.zip | |
Contract system
Diffstat (limited to 'makima/src/daemon/process/claude_protocol.rs')
| -rw-r--r-- | makima/src/daemon/process/claude_protocol.rs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/makima/src/daemon/process/claude_protocol.rs b/makima/src/daemon/process/claude_protocol.rs new file mode 100644 index 0000000..96e5377 --- /dev/null +++ b/makima/src/daemon/process/claude_protocol.rs @@ -0,0 +1,59 @@ +//! Claude Code JSON protocol types for stdin communication. +//! +//! When using `--input-format=stream-json`, Claude Code expects +//! newline-delimited JSON messages on stdin. + +use serde::Serialize; + +/// Message sent to Claude Code via stdin. +/// +/// Format based on Claude Code's stream-json input protocol. +#[derive(Debug, Clone, Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum ClaudeInputMessage { + /// A user message to send to Claude. + User { message: UserMessage }, +} + +/// The inner user message structure. +#[derive(Debug, Clone, Serialize)] +pub struct UserMessage { + /// Always "user" for user messages. + pub role: String, + /// The message content. + pub content: String, +} + +impl ClaudeInputMessage { + /// Create a new user message. + pub fn user(content: impl Into<String>) -> Self { + Self::User { + message: UserMessage { + role: "user".to_string(), + content: content.into(), + }, + } + } + + /// Serialize to a JSON string with trailing newline (NDJSON format). + pub fn to_json_line(&self) -> Result<String, serde_json::Error> { + let mut json = serde_json::to_string(self)?; + json.push('\n'); + Ok(json) + } +} + +#[cfg(test)] +mod tests { + use crate::daemon::*; + + #[test] + fn test_user_message_serialization() { + let msg = ClaudeInputMessage::user("Hello, Claude!"); + let json = msg.to_json_line().unwrap(); + + // Should produce: {"type":"user","message":{"role":"user","content":"Hello, Claude!"}}\n + assert!(json.starts_with(r#"{"type":"user","message":{"role":"user","content":"Hello, Claude!"}}"#)); + assert!(json.ends_with('\n')); + } +} |
