feat: AI 工具架构重构与微信增强 (0.2.17 → 0.2.22)
0.2.17 收束模型初始工具列表: - 仅暴露 query_capabilities/query_capability_detail/call_capability 三个入口 - API 能力统一通过 iAs HTTP API 封装,删除重复 YAML 工具 0.2.18 系统提示词拆分: - 固定系统提示词硬编码,动态附加部分 AI 可维护 - 新增 update_additional_system_prompt 能力和持久化 0.2.19 上下文增强与打断语义: - /new 拥有最高打断语义,取消运行中任务并清除当前 turn - raw_message JSONB 原文入库,群聊按 group_id 隔离作用域 - 工具调用说明替代动态附加系统提示词 0.2.20 微信输入中状态: - 改用官方 getconfig + sendtyping 流程,显式管理 typing 状态 0.2.21 API 文档功能分组: - /v1/api-docs 返回 groups,帮助 AI 按功能面发现接口 0.2.22 AI API 能力去重: - 移除与 HTTP endpoint 重复的专用能力,统一用 query_api_docs + call_http_api - 删除不再编译的 web/memory 工具文件
This commit is contained in:
@@ -7,7 +7,8 @@ use sqlx::PgPool;
|
||||
|
||||
use crate::model::{
|
||||
ContextScope, MemoryCreateRequest, MemoryDeleteRequest, MemoryDeleteResponse, MemoryResponse,
|
||||
MemorySearchRequest, MemorySearchResponse, MemoryUpdateRequest,
|
||||
MemorySearchRequest, MemorySearchResponse, MemoryUpdateRequest, ToolCallInstructionGetRequest,
|
||||
ToolCallInstructionResponse, ToolCallInstructionUpdateRequest,
|
||||
};
|
||||
use crate::repository::ContextRepository;
|
||||
|
||||
@@ -35,6 +36,10 @@ where
|
||||
"/v1/context/memories/{id}",
|
||||
patch(update_memory).delete(delete_memory),
|
||||
)
|
||||
.route(
|
||||
"/v1/context/tool-instructions",
|
||||
post(get_tool_call_instruction).patch(update_tool_call_instruction),
|
||||
)
|
||||
.layer(Extension(ContextRouteState::new(db)))
|
||||
}
|
||||
|
||||
@@ -123,6 +128,44 @@ async fn delete_memory(
|
||||
}))
|
||||
}
|
||||
|
||||
async fn update_tool_call_instruction(
|
||||
headers: HeaderMap,
|
||||
Extension(state): Extension<ContextRouteState>,
|
||||
Json(request): Json<ToolCallInstructionUpdateRequest>,
|
||||
) -> Result<Json<ToolCallInstructionResponse>, ApiError> {
|
||||
authorize(&headers)?;
|
||||
let scope = validate_scope(request.identity.scope())?;
|
||||
let content = normalize_prompt_content(request.content)?;
|
||||
let reason = optional_limited_text(request.reason, 500);
|
||||
|
||||
let instruction =
|
||||
ContextRepository::upsert_tool_call_instruction(&state.db, &scope, content, reason, "ai")
|
||||
.await
|
||||
.map_err(api_internal_error)?;
|
||||
|
||||
Ok(Json(ToolCallInstructionResponse {
|
||||
success: true,
|
||||
instruction: Some(instruction),
|
||||
}))
|
||||
}
|
||||
|
||||
async fn get_tool_call_instruction(
|
||||
headers: HeaderMap,
|
||||
Extension(state): Extension<ContextRouteState>,
|
||||
Json(request): Json<ToolCallInstructionGetRequest>,
|
||||
) -> Result<Json<ToolCallInstructionResponse>, ApiError> {
|
||||
authorize(&headers)?;
|
||||
let scope = validate_scope(request.identity.scope())?;
|
||||
let instruction = ContextRepository::get_tool_call_instruction(&state.db, &scope.scope_key)
|
||||
.await
|
||||
.map_err(api_internal_error)?;
|
||||
|
||||
Ok(Json(ToolCallInstructionResponse {
|
||||
success: true,
|
||||
instruction,
|
||||
}))
|
||||
}
|
||||
|
||||
fn authorize(headers: &HeaderMap) -> Result<(), ApiError> {
|
||||
let expected = context_api_key()?;
|
||||
let token = headers
|
||||
@@ -176,6 +219,20 @@ fn required_text(value: &str, field: &str) -> Result<String, ApiError> {
|
||||
Ok(value.to_string())
|
||||
}
|
||||
|
||||
fn normalize_prompt_content(value: String) -> Result<String, ApiError> {
|
||||
let value = value.trim().to_string();
|
||||
if value.chars().count() > 8_000 {
|
||||
return Err(api_bad_request("content 不能超过 8000 个字符"));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn optional_limited_text(value: Option<String>, max_chars: usize) -> Option<String> {
|
||||
value
|
||||
.map(|value| value.trim().chars().take(max_chars).collect::<String>())
|
||||
.filter(|value| !value.is_empty())
|
||||
}
|
||||
|
||||
fn api_bad_request(message: impl Into<String>) -> ApiError {
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
||||
Reference in New Issue
Block a user