Skip to content

Commit 41a9532

Browse files
committed
fix conversation workflow; add detailed debugging info
1 parent 9355e09 commit 41a9532

5 files changed

Lines changed: 218 additions & 52 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
A blazingly fast, interactive AI coding assistant powered by Claude, implemented in pure Rust, that can generate code, edit files, and search the web - all from your terminal.
66

7-
<div style="text-align: center;"><img src="/assets/sofos_code.png" style="width: 700px;" alt="Ferrocrypt"></div>
7+
<div align="center"><img src="/assets/sofos_code.png" style="width: 700px;" alt="Ferrocrypt"></div>
88

99
## Features
1010

@@ -76,7 +76,7 @@ sofos --prompt "Create a hello world Rust program"
7676
-p, --prompt <TEXT> One-shot mode
7777
--model <MODEL> Claude model (default: claude-sonnet-4-5)
7878
--morph-model <MODEL> Morph model (default: morph-v3-fast)
79-
--max-tokens <N> Max response tokens (default: 4096)
79+
--max-tokens <N> Max response tokens (default: 8192)
8080
-v, --verbose Verbose logging
8181
```
8282

src/api/types.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,42 @@ use serde::{Deserialize, Serialize};
33
#[derive(Debug, Clone, Serialize, Deserialize)]
44
pub struct Message {
55
pub role: String,
6-
pub content: String,
6+
#[serde(flatten)]
7+
pub content: MessageContent,
8+
}
9+
10+
#[derive(Debug, Clone, Serialize, Deserialize)]
11+
#[serde(untagged)]
12+
pub enum MessageContent {
13+
Text { content: String },
14+
Blocks { content: Vec<MessageContentBlock> },
715
}
816

917
impl Message {
1018
pub fn user(content: impl Into<String>) -> Self {
1119
Self {
1220
role: "user".to_string(),
13-
content: content.into(),
21+
content: MessageContent::Text {
22+
content: content.into(),
23+
},
1424
}
1525
}
1626

17-
pub fn assistant(content: impl Into<String>) -> Self {
27+
pub fn assistant_with_blocks(content_blocks: Vec<MessageContentBlock>) -> Self {
1828
Self {
1929
role: "assistant".to_string(),
20-
content: content.into(),
30+
content: MessageContent::Blocks {
31+
content: content_blocks,
32+
},
33+
}
34+
}
35+
36+
pub fn user_with_tool_results(results: Vec<MessageContentBlock>) -> Self {
37+
Self {
38+
role: "user".to_string(),
39+
content: MessageContent::Blocks {
40+
content: results,
41+
},
2142
}
2243
}
2344
}
@@ -54,7 +75,7 @@ pub struct CreateMessageResponse {
5475
#[serde(rename = "model")]
5576
pub _model: String,
5677
#[serde(rename = "stop_reason")]
57-
pub _stop_reason: Option<String>,
78+
pub stop_reason: Option<String>,
5879
#[serde(rename = "usage")]
5980
pub _usage: Usage,
6081
}
@@ -72,6 +93,39 @@ pub enum ContentBlock {
7293
},
7394
}
7495

96+
#[derive(Debug, Clone, Serialize, Deserialize)]
97+
#[serde(tag = "type")]
98+
pub enum MessageContentBlock {
99+
#[serde(rename = "text")]
100+
Text { text: String },
101+
#[serde(rename = "tool_use")]
102+
ToolUse {
103+
id: String,
104+
name: String,
105+
input: serde_json::Value,
106+
},
107+
#[serde(rename = "tool_result")]
108+
ToolResult {
109+
tool_use_id: String,
110+
content: String,
111+
},
112+
}
113+
114+
impl MessageContentBlock {
115+
pub fn from_content_block(block: &ContentBlock) -> Self {
116+
match block {
117+
ContentBlock::Text { text } => MessageContentBlock::Text {
118+
text: text.clone(),
119+
},
120+
ContentBlock::ToolUse { id, name, input } => MessageContentBlock::ToolUse {
121+
id: id.clone(),
122+
name: name.clone(),
123+
input: input.clone(),
124+
},
125+
}
126+
}
127+
}
128+
75129
#[derive(Debug, Deserialize)]
76130
pub struct Usage {
77131
#[serde(rename = "input_tokens")]

src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub struct Cli {
2424
#[arg(long, default_value = "morph-v3-fast")]
2525
pub morph_model: String,
2626

27-
#[arg(long, default_value = "4096")]
27+
#[arg(long, default_value = "8192")]
2828
pub max_tokens: u32,
2929

3030
#[arg(short, long)]

src/conversation.rs

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::api::{ContentBlock, Message};
1+
use crate::api::Message;
22

33
/// Manages conversation history for the REPL
44
pub struct ConversationHistory {
@@ -71,39 +71,12 @@ Your goal is to help users with coding tasks efficiently and accurately."#,
7171
self.messages.push(Message::user(content));
7272
}
7373

74-
pub fn add_assistant_message(&mut self, content: String) {
75-
self.messages.push(Message::assistant(content));
74+
pub fn add_assistant_with_blocks(&mut self, blocks: Vec<crate::api::MessageContentBlock>) {
75+
self.messages.push(Message::assistant_with_blocks(blocks));
7676
}
7777

78-
/// Add assistant content blocks (including tool uses)
79-
pub fn add_assistant_content(&mut self, content_blocks: &[ContentBlock]) {
80-
let mut content_parts = Vec::new();
81-
82-
for block in content_blocks {
83-
match block {
84-
ContentBlock::Text { text } => {
85-
content_parts.push(text.clone());
86-
}
87-
ContentBlock::ToolUse { name, input, .. } => {
88-
content_parts.push(format!(
89-
"[Used tool: {} with input: {}]",
90-
name,
91-
serde_json::to_string_pretty(input).unwrap_or_default()
92-
));
93-
}
94-
}
95-
}
96-
97-
if !content_parts.is_empty() {
98-
self.add_assistant_message(content_parts.join("\n\n"));
99-
}
100-
}
101-
102-
pub fn add_tool_result(&mut self, tool_name: &str, result: &str) {
103-
self.messages.push(Message::user(format!(
104-
"[Tool result for {}]\n{}",
105-
tool_name, result
106-
)));
78+
pub fn add_tool_results(&mut self, results: Vec<crate::api::MessageContentBlock>) {
79+
self.messages.push(Message::user_with_tool_results(results));
10780
}
10881

10982
pub fn messages(&self) -> &[Message] {

0 commit comments

Comments
 (0)