refactor: 观测层双轴正交重构——spectra→observation、工具/API 收敛、安全韧性加固
将"以光谱为中心"的观测数据架构升级为 (Source × ProductType) 双轴正交模型,
光谱降级为与光变/测光/图像平级的产品类型之一;同步把分散的工具、API、缓存表
收敛为统一入口。新增 Gaia 光变曲线(EPOCH_PHOTOMETRY)支持。
【架构】services/spectra 整体替换为 services/observation(双轴正交)
- Source(LAMOST/Gaia/SDSS/DESI)× ProductType(Spectrum/LightCurve/Photometry/Image)
正交组合,新增源/产品类型为纯加法(OCP)
- ObservationFetcher trait + ObservationRegistry:每个有效组合实现一个 fetcher,
启动时注册;SDSS specobj/APOGEE 共用 key 按 subtype 二级路由
- cone 缓存逻辑模板方法化(trait 默认方法),消除各源 4 份重复代码
- 多文件 Artifact 模型:一个逻辑产物可含多文件(如 Gaia 光变 G/BP/RP 三波段各一 FITS)
- 统一编排 dispatch.rs:search(仅检索)/ download(检索+下载),支持坐标模式
(cone→选源→下载)与标识符模式(直按 ID 下载)双输入
【Agent 工具整合】26 → 24
- 新增 find_observation:跨源×跨产品×双模式统一观测下载,取代 find_spectrum
- catalog_operation 升级为 6 合 1(search/describe/query/cone/export/lookup),
取代独立的 query_vizier + cone_search
- citation_network + library_search 合并为 library.rs
【API 路由】
- 新增 /observation/{search,download,capabilities,list} 命名空间
- 移除 /catalog/{crossmatch,spectrum/download,spectrum/list}
- GET /observation/capabilities 暴露 registry 能力清单,前端动态渲染源/产品/版本
下拉(不再硬编码各源支持矩阵)
【数据库迁移】
- 新表 observation_cache:新增 product 列 + artifacts_json(多文件产物),无 TTL
(观测数据不可变,区别于 vizier_query_cache 的 7 天 TTL)
- 20260705140001:spectrum_cache 旧数据迁入 observation_cache,单文件→单元素 artifacts
【前端】
- 新 ObservationPanel(988 行):双视图(检索下载 / 缓存库),选项由 capabilities 动态生成
- 新 useObservation hook、ObservationResultCard、observation/constants、utils/apiError
【安全与韧性加固】
- sessions 锁 Mutex → RwLock(读多写少,降低争用)
- 新增 upload_rate_limiter;login_rate_limiter 容量保护(10000 上限,超限清最旧一半)
- bookmarklet API 密钥 SHA-1 → SHA-256;ADMIN_PASSWORD 长度上限 128
- *_TIMEOUT_SECS / EMBEDDING_DIM 非法值告警并回退默认;DB_POOL_SIZE 可配置(原硬编码 5)
- sqlite-vec 注册逻辑下沉至 utils::register_sqlite_vec_extension
This commit is contained in:
+15
-12
@@ -237,12 +237,12 @@ impl AgentRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
/// 返回当前运行指标快照(锁异常时返回默认值)
|
||||
/// 返回当前运行指标快照(锁异常时返回默认值并记录警告)
|
||||
pub fn get_metrics(&self) -> super::hooks::MetricsData {
|
||||
self.metrics_data
|
||||
.try_lock()
|
||||
.map(|m| m.clone())
|
||||
.unwrap_or_default()
|
||||
self.metrics_data.try_lock().map(|m| m.clone()).unwrap_or_else(|_| {
|
||||
warn!("[AgentRuntime] 获取指标锁失败,返回默认值");
|
||||
super::hooks::MetricsData::default()
|
||||
})
|
||||
}
|
||||
|
||||
/// 设置是否启用 LLM 思考模式(向后兼容,优先使用 mode 设置)
|
||||
@@ -306,8 +306,8 @@ impl AgentRuntime {
|
||||
}
|
||||
};
|
||||
|
||||
// 压缩前捕获消息快照(用于记忆提取桥接,P3)
|
||||
let pre_compact_snapshot: Vec<crate::clients::llm::ChatMessage> = messages.to_vec();
|
||||
// 压缩前预提取记忆片段(避免克隆整个消息列表,仅提取前 400 字符的摘要)
|
||||
let pre_compact_snippets = compact::extract_snippets(messages);
|
||||
|
||||
compact::compress_context_with_hooks_and_log(
|
||||
messages,
|
||||
@@ -321,8 +321,8 @@ impl AgentRuntime {
|
||||
.await;
|
||||
|
||||
// 压缩后提取记忆(P3 桥接:将丢弃的消息内容喂给记忆提取子代理)
|
||||
compact::extract_memories_from_compaction(
|
||||
&pre_compact_snapshot,
|
||||
compact::spawn_memory_extraction_from_snippets(
|
||||
pre_compact_snippets,
|
||||
session_id,
|
||||
self.app_state.memory_manager.clone(),
|
||||
self.app_state.clone(),
|
||||
@@ -545,13 +545,16 @@ impl AgentRuntime {
|
||||
let estimated_tokens = match last_api_prompt_tokens {
|
||||
Some(last_tokens) => {
|
||||
let new_msg_count = messages.len().saturating_sub(msg_count_at_last_call);
|
||||
let new_tokens_estimate: u32 = messages
|
||||
let new_tokens_estimate: usize = messages
|
||||
.iter()
|
||||
.rev()
|
||||
.take(new_msg_count)
|
||||
.map(|m| (m.content.as_ref().map_or(0, |c| c.len()) + 4) as u32)
|
||||
.map(|m| {
|
||||
let content_len = m.content.as_ref().map_or(0, |c| c.len());
|
||||
content_len / 3 + 4 // 粗略估算:~3 字符/token + 消息 overhead
|
||||
})
|
||||
.sum();
|
||||
(last_tokens + new_tokens_estimate) as usize
|
||||
last_tokens as usize + new_tokens_estimate
|
||||
}
|
||||
None => compact::rough_estimate_tokens(messages),
|
||||
};
|
||||
|
||||
@@ -608,6 +608,9 @@ mod tests {
|
||||
120,
|
||||
)
|
||||
.unwrap(),
|
||||
observation_registry: std::sync::Arc::new(
|
||||
crate::services::observation::ObservationRegistry::default(),
|
||||
),
|
||||
llm: llm.clone(),
|
||||
medium_llm: llm.clone(),
|
||||
fast_llm: llm.clone(),
|
||||
@@ -633,8 +636,9 @@ mod tests {
|
||||
memory_manager: Arc::new(tokio::sync::Mutex::new(MemoryManager::new(PathBuf::from(
|
||||
"/tmp/test_mem",
|
||||
)))),
|
||||
sessions: Arc::new(tokio::sync::Mutex::new(std::collections::HashMap::new())),
|
||||
sessions: Arc::new(tokio::sync::RwLock::new(std::collections::HashMap::new())),
|
||||
login_rate_limiter: Arc::new(tokio::sync::Mutex::new(std::collections::HashMap::new())),
|
||||
upload_rate_limiter: Arc::new(tokio::sync::Mutex::new(std::collections::HashMap::new())),
|
||||
});
|
||||
|
||||
ToolContext::new(app_state)
|
||||
|
||||
Reference in New Issue
Block a user