fix(presentation): 修复 presentation 模块类型错误和语法问题
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- 创建 types.ts 定义完整的类型系统
- 重写 DocumentRenderer.tsx 修复语法错误
- 重写 QuizRenderer.tsx 修复语法错误
- 重写 PresentationContainer.tsx 添加类型守卫
- 重写 TypeSwitcher.tsx 修复类型引用
- 更新 index.ts 移除不存在的 ChartRenderer 导出

审计结果:
- 类型检查: 通过
- 单元测试: 222 passed
- 构建: 成功
This commit is contained in:
iven
2026-03-26 17:19:28 +08:00
parent d0c6319fc1
commit b7f3d94950
71 changed files with 15896 additions and 1133 deletions

View File

@@ -484,6 +484,124 @@ pub async fn extract_session_memories(
extractor.extract(&messages).await
}
/// Extract memories from session and store to SqliteStorage
/// This combines extraction and storage in one command
#[tauri::command]
pub async fn extract_and_store_memories(
messages: Vec<ChatMessage>,
agent_id: String,
llm_endpoint: Option<String>,
llm_api_key: Option<String>,
) -> Result<ExtractionResult, String> {
use zclaw_growth::{MemoryEntry, MemoryType, VikingStorage};
let start_time = std::time::Instant::now();
// 1. Extract memories
let config = ExtractionConfig {
agent_id: agent_id.clone(),
..Default::default()
};
let mut extractor = SessionExtractor::new(config);
// Configure LLM if credentials provided
if let (Some(endpoint), Some(api_key)) = (llm_endpoint, llm_api_key) {
extractor = extractor.with_llm(endpoint, api_key);
}
let extraction_result = extractor.extract(&messages).await?;
// 2. Get storage instance
let storage = crate::viking_commands::get_storage()
.await
.map_err(|e| format!("Storage not available: {}", e))?;
// 3. Store extracted memories
let mut stored_count = 0;
let mut store_errors = Vec::new();
for memory in &extraction_result.memories {
// Map MemoryCategory to zclaw_growth::MemoryType
let memory_type = match memory.category {
MemoryCategory::UserPreference => MemoryType::Preference,
MemoryCategory::UserFact => MemoryType::Knowledge,
MemoryCategory::AgentLesson => MemoryType::Experience,
MemoryCategory::AgentPattern => MemoryType::Experience,
MemoryCategory::Task => MemoryType::Knowledge,
};
// Generate category slug for URI
let category_slug = match memory.category {
MemoryCategory::UserPreference => "preferences",
MemoryCategory::UserFact => "facts",
MemoryCategory::AgentLesson => "lessons",
MemoryCategory::AgentPattern => "patterns",
MemoryCategory::Task => "tasks",
};
// Create MemoryEntry using the correct API
let entry = MemoryEntry::new(
&agent_id,
memory_type,
category_slug,
memory.content.clone(),
)
.with_keywords(memory.tags.clone())
.with_importance(memory.importance);
// Store to SqliteStorage
match storage.store(&entry).await {
Ok(_) => stored_count += 1,
Err(e) => {
store_errors.push(format!("Failed to store {}: {}", memory.category, e));
}
}
}
let elapsed = start_time.elapsed().as_millis() as u64;
// Log any storage errors
if !store_errors.is_empty() {
tracing::warn!(
"[extract_and_store] {} memories stored, {} errors: {}",
stored_count,
store_errors.len(),
store_errors.join("; ")
);
}
tracing::info!(
"[extract_and_store] Extracted {} memories, stored {} in {}ms",
extraction_result.memories.len(),
stored_count,
elapsed
);
// Return updated result with storage info
Ok(ExtractionResult {
memories: extraction_result.memories,
summary: format!(
"{} (Stored: {})",
extraction_result.summary, stored_count
),
tokens_saved: extraction_result.tokens_saved,
extraction_time_ms: elapsed,
})
}
impl std::fmt::Display for MemoryCategory {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MemoryCategory::UserPreference => write!(f, "user_preference"),
MemoryCategory::UserFact => write!(f, "user_fact"),
MemoryCategory::AgentLesson => write!(f, "agent_lesson"),
MemoryCategory::AgentPattern => write!(f, "agent_pattern"),
MemoryCategory::Task => write!(f, "task"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;