核心架构重构: - Config 按职责拆分为 LlmConfig/EmbeddingConfig/VisionConfig/CdsConfig/StorageConfig 五个子结构 - AppState 拆分为 LlmState/DataSourceState/SessionState 三个子结构,消除 50+ 平铺字段 - 新增 ServiceError 结构化错误类型替代 handler 中的 msg.contains() 字符串匹配 - 移除 api::handlers 兼容命名空间,路由直接引用 agent/auth/papers 等模块 认证性能优化: - login_rate_limiter/upload_rate_limiter 从 Mutex<HashMap> 迁移为 DashMap(无锁) - 新增 session_last_active: DashMap<String, AtomicU64>,auth 中间件快速路径免写锁 - 会话过期清理改为按间隔触发(300s),避免每次请求全表扫描 - MAX_SESSIONS 1000→10000,SSE 广播通道 256→1024 Agent 工具增强: - AgentTool trait 新增 is_internal()/display_name(),SSE 事件携带工具元数据 - 新增 GET /chat/tools 端点暴露注册工具列表 - pending_questions/pending_permissions 增加 created_at 时间戳,自动清理过期条目(10min TTL) - Agent 超时现在正确 abort 后台任务并设置取消令牌 观测数据源修复: - FITS 解析: APOGEE/DESI 改用 read_image+切片替代 read_rows(修复 fitsio panic) - ZTF: CIRCLE 参数分隔符 +→空格(修复 IRSA 400),半径自动裁剪至硬上限 - MAST TESS: parse_tic_json 兼容数组/对象两种 API 响应格式 - 统一检索: per_target_limit 默认 50→1,sources 支持 per-source release/version - Gaia 测光从 VizieR 镜像切换至官方 TAP 服务 RAG 并发优化: - 向量化降级从串行改为并发 5 条/批(buffer_unordered) - 混合检索 RRF 合并从借用改为 owned RetrievalResult 安全加固: - PDF 中间件: URL 解码 %2F/%2E 后判扩展名;文件名过滤非 ASCII + 禁 \ 防头注入 - chat_agent 日志截断问题内容至 50 字符;list_sessions 强制 limit clamp 前端双主题: - 设计令牌三层架构: primitive→semantic→component,浅色暖纸张学术/暗色 Night Indigo - useTheme hook + ThemeToggle 侧边栏组件 + main.tsx 防 FOUC 初始化 - 全组件从硬编码 slate 色迁移至语义令牌(bg-surface/text-content/border-subtle 等) - 新增 ToastContainer 非阻塞通知系统 部署优化: - deploy.sh 引入 SSH ControlMaster 单次密码复用
82 lines
2.8 KiB
Rust
82 lines
2.8 KiB
Rust
// src/agent/tools/astro/research/metadata.rs
|
||
// GetPaperMetadataTool — 查询文献完整元数据
|
||
|
||
use async_trait::async_trait;
|
||
use serde_json::json;
|
||
use tracing::info;
|
||
|
||
use crate::agent::tools::{AgentTool, ToolContext, ToolOutput};
|
||
|
||
pub struct GetPaperMetadataTool;
|
||
|
||
#[async_trait]
|
||
impl AgentTool for GetPaperMetadataTool {
|
||
fn name(&self) -> &str {
|
||
"get_paper_metadata"
|
||
}
|
||
|
||
fn display_name(&self) -> &str {
|
||
"获取文献信息"
|
||
}
|
||
|
||
fn description(&self) -> &str {
|
||
"获取指定文献的完整元数据信息(包括完整标题、所有作者、出版期刊、关键字、引用数、完整摘要等)。\
|
||
适用于:需要查看某篇文献的详细信息、阅读完整摘要以评估文献相关性。"
|
||
}
|
||
|
||
fn parameters(&self) -> serde_json::Value {
|
||
json!({
|
||
"type": "object",
|
||
"properties": {
|
||
"bibcode": {
|
||
"type": "string",
|
||
"description": "文献的唯一标识符,支持 ADS Bibcode(如 '2024ApJ...960..123A')、DOI 或 arXiv ID"
|
||
}
|
||
},
|
||
"required": ["bibcode"]
|
||
})
|
||
}
|
||
|
||
fn group(&self) -> &str {
|
||
"as:research"
|
||
}
|
||
|
||
fn is_concurrency_safe(&self, _args: &serde_json::Value) -> bool {
|
||
true
|
||
}
|
||
|
||
fn is_readonly(&self) -> bool {
|
||
true
|
||
}
|
||
|
||
async fn execute(&self, args: serde_json::Value, ctx: &ToolContext) -> ToolOutput {
|
||
let bibcode = match args.get("bibcode").and_then(|b| b.as_str()) {
|
||
Some(b) => b.to_string(),
|
||
None => return ToolOutput::error("缺少必需参数 'bibcode'"),
|
||
};
|
||
|
||
info!("[GetPaperMetadata] 获取文献元数据: {}", bibcode);
|
||
let state = &ctx.app_state;
|
||
|
||
match crate::services::paper::get_paper_from_db(
|
||
&state.db,
|
||
&state.config.storage.library_dir,
|
||
&bibcode,
|
||
)
|
||
.await
|
||
{
|
||
Ok(paper) => {
|
||
let content = format!(
|
||
"文献元数据 [{}]:\n 标题: {}\n 作者: {}\n 年份: {}\n 期刊: {}\n 关键字: {}\n DOI: {}\n arXiv ID: {}\n 引用数: {} 次\n 参考文献数: {} 次\n 文献类型: {}\n 已下载: {}\n 已解析为 Markdown: {}\n 摘要:\n{}",
|
||
paper.bibcode, paper.title, paper.authors.join(", "), paper.year,
|
||
paper.pub_journal, paper.keywords.join(", "), paper.doi, paper.arxiv_id,
|
||
paper.citation_count, paper.reference_count, paper.doctype,
|
||
paper.is_downloaded, paper.has_markdown, paper.abstract_text
|
||
);
|
||
ToolOutput::success(content, json!(paper))
|
||
}
|
||
Err(e) => ToolOutput::error(format!("获取文献 {} 元数据失败: {}", bibcode, e)),
|
||
}
|
||
}
|
||
}
|