fix(agent): skip reasoning_effort when think=false to avoid API errors
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions

This commit is contained in:
ZhenYi 2026-04-18 19:41:59 +08:00
parent 168f14fbac
commit 9336250f1c
6 changed files with 41 additions and 7 deletions

View File

@ -19,7 +19,7 @@ use crate::compact::{CompactConfig, CompactService};
use crate::embed::EmbedService; use crate::embed::EmbedService;
use crate::error::{AgentError, Result}; use crate::error::{AgentError, Result};
use crate::perception::{PerceptionService, SkillEntry, ToolCallEvent}; use crate::perception::{PerceptionService, SkillEntry, ToolCallEvent};
use crate::tool::{ToolCall, ToolContext, ToolExecutor}; use crate::tool::{ToolCall, ToolContext, ToolExecutor, registry::ToolRegistry};
/// Service for handling AI chat requests in rooms. /// Service for handling AI chat requests in rooms.
pub struct ChatService { pub struct ChatService {
@ -27,6 +27,7 @@ pub struct ChatService {
compact_service: Option<CompactService>, compact_service: Option<CompactService>,
embed_service: Option<EmbedService>, embed_service: Option<EmbedService>,
perception_service: PerceptionService, perception_service: PerceptionService,
tool_registry: Option<ToolRegistry>,
} }
impl ChatService { impl ChatService {
@ -36,6 +37,7 @@ impl ChatService {
compact_service: None, compact_service: None,
embed_service: None, embed_service: None,
perception_service: PerceptionService::default(), perception_service: PerceptionService::default(),
tool_registry: None,
} }
} }
@ -54,6 +56,11 @@ impl ChatService {
self self
} }
pub fn with_tool_registry(mut self, registry: ToolRegistry) -> Self {
self.tool_registry = Some(registry);
self
}
#[allow(deprecated)] #[allow(deprecated)]
pub async fn process(&self, request: AiRequest) -> Result<String> { pub async fn process(&self, request: AiRequest) -> Result<String> {
let tools: Vec<ChatCompletionTool> = request.tools.clone().unwrap_or_default(); let tools: Vec<ChatCompletionTool> = request.tools.clone().unwrap_or_default();
@ -390,6 +397,11 @@ impl ChatService {
) )
.with_project(request.project.id); .with_project(request.project.id);
// Add pre-configured tool registry if available
if let Some(ref registry) = self.tool_registry {
ctx.registry_mut().merge(registry.clone());
}
let executor = ToolExecutor::new(); let executor = ToolExecutor::new();
let results = executor let results = executor

View File

@ -130,4 +130,9 @@ impl ToolContext {
pub fn registry(&self) -> &ToolRegistry { pub fn registry(&self) -> &ToolRegistry {
&self.inner.registry &self.inner.registry
} }
/// Mutable access to registry for adding tools.
pub fn registry_mut(&mut self) -> &mut ToolRegistry {
&mut Arc::make_mut(&mut self.inner).registry
}
} }

View File

@ -24,4 +24,4 @@ pub use call::{ToolCall, ToolCallResult, ToolError, ToolResult};
pub use context::ToolContext; pub use context::ToolContext;
pub use definition::{ToolDefinition, ToolParam, ToolSchema}; pub use definition::{ToolDefinition, ToolParam, ToolSchema};
pub use executor::ToolExecutor; pub use executor::ToolExecutor;
pub use registry::ToolRegistry; pub use registry::{ToolHandler, ToolRegistry};

View File

@ -92,4 +92,18 @@ impl ToolRegistry {
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.handlers.is_empty() self.handlers.is_empty()
} }
/// Merges another registry's tools into this one.
/// Panics if a tool with the same name already exists.
pub fn merge(&mut self, other: ToolRegistry) {
for (name, handler) in other.handlers {
if self.handlers.contains_key(&name) {
panic!("tool already registered: {}", name);
}
self.handlers.insert(name, handler);
}
for (name, def) in other.definitions {
self.definitions.insert(name, def);
}
}
} }

View File

@ -1,6 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use ::agent::chat::ChatService; use ::agent::chat::ChatService;
use ::agent::tool::ToolRegistry;
use ::agent::task::service::TaskService; use ::agent::task::service::TaskService;
use async_openai::config::OpenAIConfig; use async_openai::config::OpenAIConfig;
use avatar::AppAvatar; use avatar::AppAvatar;
@ -145,7 +146,9 @@ impl AppService {
.with_api_key(&api_key) .with_api_key(&api_key)
.with_api_base(&base_url); .with_api_base(&base_url);
let client = async_openai::Client::with_config(cfg); let client = async_openai::Client::with_config(cfg);
Some(Arc::new(ChatService::new(client))) let mut registry = ToolRegistry::new();
git_tools::register_all(&mut registry);
Some(Arc::new(ChatService::new(client).with_tool_registry(registry)))
} }
(Err(e), _) => { (Err(e), _) => {
slog::warn!(logs, "AI chat disabled — {}", e); slog::warn!(logs, "AI chat disabled — {}", e);

View File

@ -1,7 +1,6 @@
use crate::AppService; use crate::AppService;
use crate::error::AppError; use crate::error::AppError;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use futures::future::join_all;
use models::projects::{ use models::projects::{
project, MemberRole, project_audit_log, project_member_invitations, project_members, project, MemberRole, project_audit_log, project_member_invitations, project_members,
}; };
@ -165,12 +164,13 @@ impl AppService {
.count(&self.db) .count(&self.db)
.await?; .await?;
let invitations = join_all( let invitations = futures::future::join_all(
invitations invitations
.into_iter() .into_iter()
.map(|inv| InvitationResponse::from_model(inv, self.db.writer())), .map(|inv| InvitationResponse::from_model(inv, self.db.writer())),
) )
.await; .await
.into_iter()
.collect(); .collect();
Ok(InvitationListResponse { Ok(InvitationListResponse {