feat(agent): pass AppConfig through ToolContext and fix tool call handling

This commit is contained in:
ZhenYi 2026-04-20 19:32:03 +08:00
parent 4e955d9ae3
commit a0ab16e6ea
3 changed files with 30 additions and 9 deletions

View File

@ -8,6 +8,7 @@ use models::projects::project;
use models::repos::repo; use models::repos::repo;
use models::rooms::{room, room_message}; use models::rooms::{room, room_message};
use models::users::user; use models::users::user;
use config::AppConfig;
use std::collections::HashMap; use std::collections::HashMap;
use uuid::Uuid; use uuid::Uuid;
@ -29,6 +30,7 @@ pub type StreamCallback = Box<
pub struct AiRequest { pub struct AiRequest {
pub db: AppDatabase, pub db: AppDatabase,
pub cache: AppCache, pub cache: AppCache,
pub config: AppConfig,
pub model: model::Model, pub model: model::Model,
pub project: project::Model, pub project: project::Model,
pub sender: user::Model, pub sender: user::Model,

View File

@ -321,13 +321,6 @@ impl ChatService {
); );
if has_tool_calls && tools_enabled { if has_tool_calls && tools_enabled {
// Send final text chunk
on_chunk(AiStreamChunk {
content: text_accumulated.clone(),
done: true,
})
.await;
// Build ToolCall list from accumulated chunks // Build ToolCall list from accumulated chunks
let tool_calls: Vec<_> = tool_call_chunks let tool_calls: Vec<_> = tool_call_chunks
.into_iter() .into_iter()
@ -340,12 +333,23 @@ impl ChatService {
.collect(); .collect();
if !tool_calls.is_empty() { if !tool_calls.is_empty() {
// Capture thinking text, send it as a completed chunk, then clear for the next turn
let thinking_text = text_accumulated.clone();
if !thinking_text.is_empty() {
on_chunk(AiStreamChunk {
content: thinking_text.clone(),
done: true,
})
.await;
}
text_accumulated.clear();
// Append assistant message with tool calls to history // Append assistant message with tool calls to history
messages.push(ChatCompletionRequestMessage::Assistant( messages.push(ChatCompletionRequestMessage::Assistant(
ChatCompletionRequestAssistantMessage { ChatCompletionRequestAssistantMessage {
content: Some( content: Some(
ChatCompletionRequestAssistantMessageContent::Text( ChatCompletionRequestAssistantMessageContent::Text(
text_accumulated, thinking_text,
), ),
), ),
name: None, name: None,
@ -400,6 +404,7 @@ impl ChatService {
let mut ctx = ToolContext::new( let mut ctx = ToolContext::new(
request.db.clone(), request.db.clone(),
request.cache.clone(), request.cache.clone(),
request.config.clone(),
request.room.id, request.room.id,
Some(request.sender.uid), Some(request.sender.uid),
) )

View File

@ -7,6 +7,7 @@ use std::sync::Arc;
use db::cache::AppCache; use db::cache::AppCache;
use db::database::AppDatabase; use db::database::AppDatabase;
use config::AppConfig;
use uuid::Uuid; use uuid::Uuid;
use super::registry::ToolRegistry; use super::registry::ToolRegistry;
@ -21,6 +22,7 @@ pub struct ToolContext {
struct Inner { struct Inner {
pub db: AppDatabase, pub db: AppDatabase,
pub cache: AppCache, pub cache: AppCache,
pub config: AppConfig,
pub room_id: Uuid, pub room_id: Uuid,
pub sender_id: Option<Uuid>, pub sender_id: Option<Uuid>,
pub project_id: Uuid, pub project_id: Uuid,
@ -32,11 +34,18 @@ struct Inner {
} }
impl ToolContext { impl ToolContext {
pub fn new(db: AppDatabase, cache: AppCache, room_id: Uuid, sender_id: Option<Uuid>) -> Self { pub fn new(
db: AppDatabase,
cache: AppCache,
config: AppConfig,
room_id: Uuid,
sender_id: Option<Uuid>,
) -> Self {
Self { Self {
inner: Arc::new(Inner { inner: Arc::new(Inner {
db, db,
cache, cache,
config,
room_id, room_id,
sender_id, sender_id,
project_id: Uuid::nil(), project_id: Uuid::nil(),
@ -111,6 +120,11 @@ impl ToolContext {
&self.inner.cache &self.inner.cache
} }
/// Application config.
pub fn config(&self) -> &AppConfig {
&self.inner.config
}
/// Room where the original message was sent. /// Room where the original message was sent.
pub fn room_id(&self) -> Uuid { pub fn room_id(&self) -> Uuid {
self.inner.room_id self.inner.room_id