// 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)), } } }