优化: AR-10 想法→灵感文案统一(13 文件)
用户可见文案 + 后端错误信息 + LLM 工具描述/系统提示词 + store toast + 注释统一改灵感: i18n zh-CN(ideas/aiTool/projectDetail) + idea.rs 错误 + tool_registry/prompt LLM + stores/project toast + api/views 注释 en 版待定(用 Ideas/Idea)+ docs/crates 注释低优先本轮略;cargo check/vue-tsc 0 error
This commit is contained in:
@@ -44,7 +44,7 @@ pub(crate) fn risk_from_str(s: &str) -> Option<RiskLevel> {
|
||||
/// - delete_project/restore_project/purge_project → "删除/恢复/清除项目"+id
|
||||
/// - update_project → "修改项目"+field
|
||||
/// - bind_directory → "绑定目录"+path
|
||||
/// - create_task → "创建任务"+title;create_project → "创建项目"+name;create_idea → "捕获想法"+title
|
||||
/// - create_task → "创建任务"+title;create_project → "创建项目"+name;create_idea → "捕获灵感"+title
|
||||
/// - run_workflow → "运行工作流"+name
|
||||
/// args 无可读字段或工具未特化时,fallback 原 risk 模板(含风险等级提示)。
|
||||
fn build_approval_reason(tool_name: &str, args: &serde_json::Value, risk_level: RiskLevel) -> String {
|
||||
@@ -80,7 +80,7 @@ fn build_approval_reason(tool_name: &str, args: &serde_json::Value, risk_level:
|
||||
}
|
||||
"create_idea" => {
|
||||
let title = s("title");
|
||||
if !title.is_empty() { format!("捕获想法:{}", title) } else { String::new() }
|
||||
if !title.is_empty() { format!("捕获灵感:{}", title) } else { String::new() }
|
||||
}
|
||||
"run_workflow" => {
|
||||
let name = s("name");
|
||||
|
||||
@@ -49,11 +49,11 @@ fn system_prompt_parts(lang: &str) -> (&'static str, &'static str) {
|
||||
"\n## Current Projects\n",
|
||||
),
|
||||
_ => (
|
||||
"你是 DevFlow 的 AI 助手。你帮助用户管理项目、任务、想法和工作流。\n\
|
||||
"你是 DevFlow 的 AI 助手。你帮助用户管理项目、任务、灵感和工作流。\n\
|
||||
必须使用简体中文回复,禁止使用繁体中文字符。\n\n\
|
||||
## 当前能力\n\
|
||||
你可以通过工具调用执行以下操作:\n\
|
||||
- 创建/查询项目、任务、想法\n\
|
||||
- 创建/查询项目、任务、灵感\n\
|
||||
- 运行工作流\n\
|
||||
- 读取文件内容、列出目录、创建/写入文件\n\n\
|
||||
## 行为准则\n\
|
||||
|
||||
@@ -109,7 +109,7 @@ pub fn build_ai_tool_registry(db: &Arc<Database>) -> AiToolRegistry {
|
||||
})},
|
||||
);
|
||||
registry.register(
|
||||
"list_ideas", "列出所有想法",
|
||||
"list_ideas", "列出所有灵感",
|
||||
df_ai::ai_tools::object_schema(vec![]), RiskLevel::Low,
|
||||
{ let db = db.clone(); Box::new(move |_args: serde_json::Value| {
|
||||
let db = db.clone();
|
||||
@@ -265,7 +265,7 @@ pub fn build_ai_tool_registry(db: &Arc<Database>) -> AiToolRegistry {
|
||||
})},
|
||||
);
|
||||
registry.register(
|
||||
"create_idea", "捕获一个新想法",
|
||||
"create_idea", "捕获一个新灵感",
|
||||
df_ai::ai_tools::object_schema(vec![("title", "string", true), ("description", "string", false), ("tags", "string", false), ("source", "string", false)]),
|
||||
RiskLevel::Medium,
|
||||
{ let db = db.clone(); Box::new(move |args: serde_json::Value| {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! 想法相关命令
|
||||
//! 灵感相关命令
|
||||
|
||||
use serde::Deserialize;
|
||||
use tauri::State;
|
||||
@@ -11,7 +11,7 @@ use crate::state::AppState;
|
||||
|
||||
use super::now_millis;
|
||||
|
||||
/// 创建想法入参
|
||||
/// 创建灵感入参
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CreateIdeaInput {
|
||||
pub title: String,
|
||||
@@ -28,7 +28,7 @@ fn default_priority() -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
/// 列出想法,可选按 status 过滤(指定状态走 query 走白名单索引列,否则全量)
|
||||
/// 列出灵感,可选按 status 过滤(指定状态走 query 走白名单索引列,否则全量)
|
||||
#[tauri::command]
|
||||
pub async fn list_ideas(
|
||||
state: State<'_, AppState>,
|
||||
@@ -40,7 +40,7 @@ pub async fn list_ideas(
|
||||
}
|
||||
}
|
||||
|
||||
/// 创建想法,返回完整记录
|
||||
/// 创建灵感,返回完整记录
|
||||
#[tauri::command]
|
||||
pub async fn create_idea(
|
||||
state: State<'_, AppState>,
|
||||
@@ -70,7 +70,7 @@ pub async fn create_idea(
|
||||
Ok(record)
|
||||
}
|
||||
|
||||
/// 更新想法单个字段(字段名走 df-storage 白名单校验)
|
||||
/// 更新灵感单个字段(字段名走 df-storage 白名单校验)
|
||||
#[tauri::command]
|
||||
pub async fn update_idea(
|
||||
state: State<'_, AppState>,
|
||||
@@ -85,13 +85,13 @@ pub async fn update_idea(
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// 删除想法
|
||||
/// 删除灵感
|
||||
#[tauri::command]
|
||||
pub async fn delete_idea(state: State<'_, AppState>, id: String) -> Result<bool, String> {
|
||||
state.ideas.delete(&id).await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// 将想法晋升为项目 — 复用 df-project 领域逻辑创建项目,回写想法 status=promoted/promoted_to
|
||||
/// 将灵感晋升为项目 — 复用 df-project 领域逻辑创建项目,回写灵感 status=promoted/promoted_to
|
||||
#[tauri::command]
|
||||
pub async fn promote_idea(
|
||||
state: State<'_, AppState>,
|
||||
@@ -102,10 +102,10 @@ pub async fn promote_idea(
|
||||
.get_by_id(&id)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.ok_or_else(|| format!("想法不存在: {id}"))?;
|
||||
.ok_or_else(|| format!("灵感不存在: {id}"))?;
|
||||
|
||||
if record.promoted_to.is_some() {
|
||||
return Err(format!("想法已立项: {}", record.promoted_to.unwrap()));
|
||||
return Err(format!("灵感已立项: {}", record.promoted_to.unwrap()));
|
||||
}
|
||||
|
||||
// 复用 df-project 领域逻辑构造项目实体(create_from_idea)
|
||||
@@ -133,9 +133,9 @@ pub async fn promote_idea(
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
// 回写想法:status=promoted + promoted_to(update_full 单事务覆盖可变字段)
|
||||
// 回写灵感:status=promoted + promoted_to(update_full 单事务覆盖可变字段)
|
||||
// 补偿删除:第二步失败时回滚第一步已建的 project,保证最终一致性(非原子,但防项目存留而
|
||||
// 想法状态未变的数据不一致)。Repository 方法各自持锁不支持跨 repo 共享事务对象,故选补偿
|
||||
// 灵感状态未变的数据不一致)。Repository 方法各自持锁不支持跨 repo 共享事务对象,故选补偿
|
||||
// 删除而非真事务(改动最小,工程投入产出比最高)。
|
||||
let updated = IdeaRecord {
|
||||
status: "promoted".to_string(),
|
||||
@@ -145,11 +145,11 @@ pub async fn promote_idea(
|
||||
};
|
||||
if let Err(e) = state.ideas.update_full(&updated).await {
|
||||
// 回写失败:补偿删除已建项目,避免悬空项目(idea.promoted_to 仍空,可重试立项)
|
||||
tracing::error!("想法 {id} 回写失败,补偿删除已建项目 {project_id}: {e}");
|
||||
tracing::error!("灵感 {id} 回写失败,补偿删除已建项目 {project_id}: {e}");
|
||||
if let Err(del_err) = state.projects.purge_with_descendants(&project_id).await {
|
||||
tracing::error!("补偿删除项目 {project_id} 也失败(需人工清理): {del_err}");
|
||||
}
|
||||
return Err(format!("想法立项回写失败(已回滚项目创建): {}", e));
|
||||
return Err(format!("灵感立项回写失败(已回滚项目创建): {}", e));
|
||||
}
|
||||
|
||||
Ok(df_ideas::promotion::PromotionResult {
|
||||
@@ -161,22 +161,22 @@ pub async fn promote_idea(
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 想法评估 — 多维评分 + 对抗式评估
|
||||
// 灵感评估 — 多维评分 + 对抗式评估
|
||||
// ============================================================
|
||||
|
||||
/// 评估想法:多维评分 + 对抗式评估,结果写回 scores/score/ai_analysis,状态置 pending_review,返回更新后的记录
|
||||
/// 评估灵感:多维评分 + 对抗式评估,结果写回 scores/score/ai_analysis,状态置 pending_review,返回更新后的记录
|
||||
#[tauri::command]
|
||||
pub async fn evaluate_idea(
|
||||
state: State<'_, AppState>,
|
||||
id: String,
|
||||
) -> Result<IdeaRecord, String> {
|
||||
// 取出想法
|
||||
// 取出灵感
|
||||
let record = state
|
||||
.ideas
|
||||
.get_by_id(&id)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.ok_or_else(|| format!("想法不存在: {id}"))?;
|
||||
.ok_or_else(|| format!("灵感不存在: {id}"))?;
|
||||
|
||||
let idea = record_to_idea(&record);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ pub fn run() {
|
||||
commands::task::create_task,
|
||||
commands::task::update_task,
|
||||
commands::task::delete_task,
|
||||
// 想法
|
||||
// 灵感
|
||||
commands::idea::list_ideas,
|
||||
commands::idea::create_idea,
|
||||
commands::idea::update_idea,
|
||||
|
||||
@@ -135,7 +135,7 @@ impl LlmConcurrency {
|
||||
pub struct AppState {
|
||||
/// 数据库句柄(Arc 包装,便于在异步任务中重建 Repo)
|
||||
pub db: Arc<Database>,
|
||||
/// 想法表 Repo
|
||||
/// 灵感表 Repo
|
||||
pub ideas: IdeaRepo,
|
||||
/// 项目表 Repo
|
||||
pub projects: ProjectRepo,
|
||||
|
||||
Reference in New Issue
Block a user