feat: context pressure denominator, ambient sense formatting, resume timestamp, user nickname system, subagent background fork, settings LLM config, turn lifecycle, ledger lifecycle, subconscious evolution
- Context pressure footer now shows 'ctx 19% of 262k' (B-008) - Ambient sense formatting as separate timestamp marker (B-010, T-034) - Resume timestamp indicator with duration (T-032) - User nickname system sourced from identity frontmatter (T-033) - Subagent background fork task (B-009, T-031) - Settings LLM config task (T-030) - Turn lifecycle and sensorium completion task - Ledger entry lifecycle task - Subconscious evolution documentation - Multimodal input metadata task - Image support module (src/core/image.rs) - Various refactors: config, seeds, session, consciousness engine, server modules, bridge, API handlers, TUI cockpit/commands/render, health panel, presence, setup wizard - website/docs submodule update
This commit is contained in:
parent
f93f9ef45b
commit
61c2007226
30 changed files with 976 additions and 151 deletions
|
|
@ -5,7 +5,7 @@
|
|||
//! - Persists to SQLite
|
||||
//! - Can be enhanced later with full tool-calling
|
||||
|
||||
use crate::bridge::bifrost::{BifrostClient, ChatCompletionRequest, Message as BifrostMessage};
|
||||
use crate::bridge::bifrost::{BifrostClient, ChatCompletionRequest, ContentPart, ImageUrlSource, Message as BifrostMessage};
|
||||
use crate::core::session::{ContentBlock, ConversationMessage, Session};
|
||||
|
||||
pub struct ServerConversation {
|
||||
|
|
@ -41,11 +41,32 @@ impl ServerConversation {
|
|||
crate::core::session::MessageRole::Assistant => "assistant",
|
||||
crate::core::session::MessageRole::Tool => "tool",
|
||||
};
|
||||
let content = m.blocks.iter().filter_map(|b| match b {
|
||||
ContentBlock::Text { text } => Some(text.as_str()),
|
||||
_ => None,
|
||||
}).collect::<Vec<_>>().join("\n");
|
||||
BifrostMessage::text(role, content)
|
||||
|
||||
let has_images = m.blocks.iter().any(|b| matches!(b, ContentBlock::Image { .. }));
|
||||
|
||||
if has_images {
|
||||
let parts: Vec<ContentPart> = m.blocks.iter().filter_map(|b| match b {
|
||||
ContentBlock::Text { text } => Some(ContentPart::Text { text: text.clone() }),
|
||||
ContentBlock::Image { media_type, data } => {
|
||||
let url = format!("data:{media_type};base64,{data}");
|
||||
Some(ContentPart::ImageUrl { image_url: ImageUrlSource { url } })
|
||||
}
|
||||
_ => None,
|
||||
}).collect();
|
||||
|
||||
let text_content = m.blocks.iter().filter_map(|b| match b {
|
||||
ContentBlock::Text { text } => Some(text.as_str()),
|
||||
_ => None,
|
||||
}).collect::<Vec<_>>().join("\n");
|
||||
|
||||
BifrostMessage::multimodal_user(text_content, parts)
|
||||
} else {
|
||||
let content = m.blocks.iter().filter_map(|b| match b {
|
||||
ContentBlock::Text { text } => Some(text.as_str()),
|
||||
_ => None,
|
||||
}).collect::<Vec<_>>().join("\n");
|
||||
BifrostMessage::text(role, content)
|
||||
}
|
||||
}).collect();
|
||||
|
||||
// Call Bifrost
|
||||
|
|
|
|||
Loading…
Reference in a new issue