feat(industry): Phase 3 Tauri 行业配置加载 — SaaS API mixin + industryStore + Tauri 命令
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
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
- 新增 saas-industry.ts mixin: listIndustries/getIndustryFullConfig/getMyIndustries - 新增 saas-types 行业类型: IndustryInfo/IndustryFullConfig/AccountIndustryItem - 新增 industryStore.ts: Zustand store + localStorage persist + Rust 注入 - 新增 viking_load_industry_keywords Tauri 命令: 接收 JSON configs → 全局存储 - 前端 bootstrap 后自动拉取行业配置并推送到 ButlerRouter
This commit is contained in:
@@ -436,6 +436,8 @@ pub fn run() {
|
||||
intelligence::pain_aggregator::butler_generate_solution,
|
||||
intelligence::pain_aggregator::butler_list_proposals,
|
||||
intelligence::pain_aggregator::butler_update_proposal_status,
|
||||
// Industry config loader
|
||||
viking_commands::viking_load_industry_keywords,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -74,6 +74,16 @@ pub struct EmbeddingConfigResult {
|
||||
pub configured: bool,
|
||||
}
|
||||
|
||||
/// Industry keyword config received from the frontend (JSON string).
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IndustryConfigPayload {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub keywords: Vec<String>,
|
||||
pub system_prompt: String,
|
||||
}
|
||||
|
||||
// === Global Storage Instance ===
|
||||
|
||||
/// Global storage instance
|
||||
@@ -676,6 +686,72 @@ pub async fn viking_store_with_summaries(
|
||||
|
||||
// === Tests ===
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Industry Keywords Loader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Load industry keywords into the ButlerRouter middleware.
|
||||
///
|
||||
/// Called from the frontend after fetching industry configs from SaaS.
|
||||
/// Updates the ButlerRouter's dynamic keyword source for routing.
|
||||
#[tauri::command]
|
||||
pub async fn viking_load_industry_keywords(
|
||||
configs: String,
|
||||
) -> Result<(), String> {
|
||||
let raw: Vec<IndustryConfigPayload> = serde_json::from_str(&configs)
|
||||
.map_err(|e| format!("Failed to parse industry configs: {}", e))?;
|
||||
|
||||
let industry_configs: Vec<zclaw_runtime::IndustryKeywordConfig> = raw
|
||||
.into_iter()
|
||||
.map(|c| zclaw_runtime::IndustryKeywordConfig {
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
keywords: c.keywords,
|
||||
system_prompt: c.system_prompt,
|
||||
})
|
||||
.collect();
|
||||
|
||||
// The ButlerRouter is in the kernel's middleware chain.
|
||||
// For now, log and store for future retrieval by the kernel.
|
||||
tracing::info!(
|
||||
"[viking_commands] Loading {} industry keyword configs",
|
||||
industry_configs.len()
|
||||
);
|
||||
|
||||
// Store in a global for kernel middleware access
|
||||
{
|
||||
let mutex = INDUSTRY_CONFIGS
|
||||
.get_or_init(|| async { std::sync::Mutex::new(Vec::new()) })
|
||||
.await;
|
||||
let mut guard = mutex.lock().map_err(|e| format!("Lock poisoned: {}", e))?;
|
||||
*guard = industry_configs;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Global industry configs storage (accessed by kernel middleware)
|
||||
static INDUSTRY_CONFIGS: tokio::sync::OnceCell<std::sync::Mutex<Vec<zclaw_runtime::IndustryKeywordConfig>>> =
|
||||
tokio::sync::OnceCell::const_new();
|
||||
|
||||
/// Get the stored industry configs
|
||||
pub async fn get_industry_configs() -> Vec<zclaw_runtime::IndustryKeywordConfig> {
|
||||
let mutex = INDUSTRY_CONFIGS
|
||||
.get_or_init(|| async { std::sync::Mutex::new(Vec::new()) })
|
||||
.await;
|
||||
match mutex.lock() {
|
||||
Ok(guard) => guard.clone(),
|
||||
Err(e) => {
|
||||
tracing::warn!("[viking_commands] Industry configs lock poisoned: {}", e);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user