后端: - 工作流推进链(D-03):advance_task/状态机/闸门走 df-nodes Node trait,conditions 条件引擎扩展 - 想法评估闭环:启发式评分+对抗评估,df-ideas/scoring + df-storage/idea_eval_repo + idea 前端打通 - 全局事件数据总线:df-ai/context+context_helpers+augmentation 跨模块解耦 - AI planner/plan_hint/intent:aichat B 路线并行多轮基础 - patch_file 加固(TD-03/04):读改写整体锁防 lost update,expected_hash 合约闭环 - 压缩超时兜底(F-15 卡死根治) - F-09 多会话并发:LlmConcurrency per-conv + streamingGuard 前端守护 + verify 脚本 - 知识注入 DRY/skills/audit 扩展 清理: - aichat 技术债(误报 allow/死导入/过时注释 30 项) - URGENT.md 删除(11 项加急全解决/迁 todo) - 文档整理(todo/待决策/待审查/ARCHITECTURE/INDEX + 总线/技术债审查新文档)
323 lines
13 KiB
Rust
323 lines
13 KiB
Rust
//! 数据模型定义 — 与数据库表对应的 Rust 结构体
|
|
|
|
use df_ai_core::model::{deserialize_model_configs, ModelConfig};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
// ============================================================
|
|
// 想法相关模型
|
|
// ============================================================
|
|
|
|
/// 想法记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct IdeaRecord {
|
|
pub id: String,
|
|
pub title: String,
|
|
pub description: String,
|
|
pub status: String,
|
|
pub priority: i32,
|
|
pub score: Option<f64>,
|
|
pub tags: Option<String>, // JSON 数组
|
|
pub source: Option<String>,
|
|
pub promoted_to: Option<String>, // 晋升后的 project_id
|
|
pub ai_analysis: Option<String>, // AI 分析结果 JSON
|
|
pub scores: Option<String>, // 多维评分 JSON (feasibility/impact/urgency/overall)
|
|
pub related_ids: Option<String>, // 关联灵感 id JSON 数组(同 tags 模式,为关联关系 UI 打底)
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
/// 灵感评估历史记录(追加型审计表 idea_evaluations,V22)
|
|
///
|
|
/// 每次灵感 AI 评估产生一行快照,version 单调递增。
|
|
/// 替代覆写 ideas.ai_analysis / ideas.scores:保留评估历史可追溯。
|
|
/// ai_analysis/scores 为 JSON 字符串,score 为综合评分,evaluated_by 标评估发起者。
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct IdeaEvaluationRecord {
|
|
pub id: String,
|
|
pub idea_id: String,
|
|
pub version: i64,
|
|
pub ai_analysis: Option<String>,
|
|
pub scores: Option<String>,
|
|
pub score: Option<f64>,
|
|
pub evaluated_by: Option<String>,
|
|
pub evaluated_at: String,
|
|
}
|
|
|
|
// ============================================================
|
|
// 项目相关模型
|
|
// ============================================================
|
|
|
|
/// 项目记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ProjectRecord {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub description: String,
|
|
pub status: String,
|
|
pub idea_id: Option<String>,
|
|
/// 绑定的本地代码目录(绝对路径,可空=未绑定,第二步导入历史项目时复用)
|
|
pub path: Option<String>,
|
|
/// 技术栈 JSON 数组字符串(如 ["rust","vue","tauri"],由探测填充,可空)
|
|
pub stack: Option<String>,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
// ============================================================
|
|
// 任务相关模型
|
|
// ============================================================
|
|
|
|
/// 任务记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct TaskRecord {
|
|
pub id: String,
|
|
pub project_id: String,
|
|
pub title: String,
|
|
pub description: String,
|
|
pub status: String,
|
|
pub priority: i32,
|
|
pub branch_name: Option<String>,
|
|
pub assignee: Option<String>,
|
|
pub workflow_def_id: Option<String>, // 关联的工作流定义 ID
|
|
pub base_branch: Option<String>, // 基础分支
|
|
/// review 退回累计轮数(in_review→in_progress / testing→in_review 时 +1,
|
|
/// 由 advance_task 原子写入,见 df-nodes::task_advance_node)。
|
|
/// #[serde(default)] 兼容旧前端无该字段的 JSON(老任务记录默认 0)。
|
|
#[serde(default)]
|
|
pub review_rounds: i32,
|
|
/// 任务产出 JSON 字符串(AiNode 自审闭环,决策 a:task 中心,产出跟 task 走)。
|
|
///
|
|
/// 三方读写约定:ai_execute 写产出 / ai_self_review 读产出做自审 / human_review 展示产出对象。
|
|
/// 经通用 update_field 写白名单(非 status 那种状态机收口字段),TEXT NULL 向后兼容。
|
|
/// #[serde(skip_serializing_if)] 无产出不序列化(省前端字段空值),#[serde(default)] 兼容旧 JSON。
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
#[serde(default)]
|
|
pub output_json: Option<String>,
|
|
/// 关联灵感 ID(F-260619-01,1对1 单向,任务→灵感)。
|
|
/// 复用 projects.idea_id 模式(REFERENCES ideas(id) 外键),可空(任务可不关联灵感)。
|
|
/// 老任务无 idea_id → None。#[serde(default)] 兼容旧前端 JSON(无该字段时为 None)。
|
|
#[serde(default)]
|
|
pub idea_id: Option<String>,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
/// 分支记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct BranchRecord {
|
|
pub id: String,
|
|
pub project_id: String,
|
|
pub task_id: Option<String>,
|
|
pub name: String,
|
|
pub base: String,
|
|
pub status: String,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
pub merged_at: Option<String>,
|
|
}
|
|
|
|
/// 发布记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ReleaseRecord {
|
|
pub id: String,
|
|
pub project_id: String,
|
|
pub version: String,
|
|
pub status: String,
|
|
pub task_ids: String, // JSON 数组
|
|
pub changelog: Option<String>,
|
|
pub created_at: String,
|
|
pub released_at: Option<String>,
|
|
}
|
|
|
|
// ============================================================
|
|
// 工作流相关模型
|
|
// ============================================================
|
|
|
|
/// 工作流执行记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct WorkflowRecord {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub dag_json: String, // DAG 的 JSON 序列化
|
|
pub status: String,
|
|
pub triggered_by: Option<String>,
|
|
pub project_id: Option<String>, // 关联项目 ID
|
|
pub task_id: Option<String>, // 关联任务 ID
|
|
pub created_at: String,
|
|
pub completed_at: Option<String>,
|
|
}
|
|
|
|
/// 节点执行记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct NodeExecutionRecord {
|
|
pub id: String,
|
|
pub workflow_id: String,
|
|
pub node_id: String,
|
|
pub node_type: String,
|
|
pub status: String,
|
|
pub input_json: Option<String>,
|
|
pub output_json: Option<String>,
|
|
pub error_message: Option<String>,
|
|
pub started_at: Option<String>,
|
|
pub completed_at: Option<String>,
|
|
}
|
|
|
|
// ============================================================
|
|
// AI 相关模型 (V3)
|
|
// ============================================================
|
|
|
|
/// AI 提供商配置记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AiProviderRecord {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub provider_type: String,
|
|
pub api_key: String,
|
|
pub base_url: String,
|
|
pub default_model: String,
|
|
pub models: Option<String>, // JSON array of model names
|
|
/// 模型能力配置数组(F-01 阶段1,4 维度 + 路由控制)。
|
|
/// DB TEXT 列存 JSON 字符串,from_row 经 deserialize_model_configs 解析。
|
|
/// 向后兼容:老库 NULL/空/老字符串数组 → 空 Vec 或转默认 ModelConfig。default_model 保留过渡。
|
|
#[serde(default, deserialize_with = "deserialize_model_configs")]
|
|
pub model_configs: Vec<ModelConfig>,
|
|
pub is_default: bool,
|
|
pub config: Option<String>, // JSON extra config
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
/// provider 是否进入负载均衡池(F-260614-04)。false = 仅作为配置存在,不参与主链路由/选池。
|
|
/// 老库迁移默认 1(单 provider 路径零变化)。
|
|
#[serde(default = "default_enabled")]
|
|
pub enabled: bool,
|
|
/// provider 在负载均衡池中的选择权重(0-100,F-260614-04)。高权重优先被选为主;
|
|
/// 同权重时退化近似轮询。老库迁移默认 50。
|
|
#[serde(default = "default_weight")]
|
|
pub weight: u32,
|
|
}
|
|
|
|
/// AiProviderRecord.enabled 的 serde 默认(true)。老库/缺字段 JSON → enabled。
|
|
fn default_enabled() -> bool {
|
|
true
|
|
}
|
|
|
|
/// AiProviderRecord.weight 的 serde 默认(50)。老库/缺字段 JSON → 50。
|
|
fn default_weight() -> u32 {
|
|
50
|
|
}
|
|
|
|
/// AI 对话记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AiConversationRecord {
|
|
pub id: String,
|
|
pub title: Option<String>,
|
|
pub messages: String, // JSON array of ChatMessage
|
|
pub provider_id: Option<String>,
|
|
pub model: Option<String>,
|
|
pub models: Option<String>, // 用过的所有 model(JSON 数组字符串,去重)
|
|
pub archived: bool, // 是否归档(侧栏折叠展示)
|
|
pub pinned: bool, // 是否置顶(排序置前;UX-17)
|
|
pub prompt_tokens: Option<i64>, // 输入 token 累计(流式 usage 落库)
|
|
pub completion_tokens: Option<i64>, // 输出 token 累计(流式 usage 落库)
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
/// AI 工具执行审计记录
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AiToolExecutionRecord {
|
|
pub id: String,
|
|
pub conversation_id: Option<String>,
|
|
/// 消息级溯源:工具调用所属的 ChatMessage.id(F-260619-04)。
|
|
/// NULL = 老库行 / 消息级溯源未启用期的记录 / 无法关联的调用。
|
|
/// 升级后,audit 写入从 ContextManager 取当前 assistant 消息 id 填入(P1 接入,P0 只建列)。
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub message_id: Option<String>,
|
|
pub tool_call_id: String,
|
|
pub tool_name: String,
|
|
pub arguments: String,
|
|
pub result: Option<String>,
|
|
pub status: String, // pending/approved/rejected/executing/completed/failed
|
|
pub risk_level: String, // low/medium/high
|
|
pub requested_at: String,
|
|
pub executed_at: Option<String>,
|
|
pub decided_by: Option<String>, // human/auto
|
|
}
|
|
|
|
/// 消息记录(ai_messages 表,F-260619-03 消息拆分存储)。
|
|
///
|
|
/// 每条 ChatMessage 一行,替代 `ai_conversations.messages` 的整对话 JSON 列存。
|
|
/// 主键 `id` = ChatMessage.id(构造时 ULID 风格生成),(conversation_id, seq) UNIQUE
|
|
/// 保证对话内序号唯一。本结构仅承载持久化映射,P0 阶段 ContextManager 仍走旧 JSON 列,
|
|
/// 切读策略待用户决策(P2)。
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AiMessageRecord {
|
|
/// 消息全局唯一 ID(= ChatMessage.id),主键
|
|
pub id: String,
|
|
/// 关联对话 ID
|
|
pub conversation_id: String,
|
|
/// 对话内序号(排序用,从 0 起)
|
|
pub seq: i64,
|
|
/// 消息角色:system/user/assistant/tool
|
|
pub role: String,
|
|
/// 文本内容(parts 的 Text 片与 content 一致)
|
|
pub content: String,
|
|
/// 多模态 parts JSON(可空)
|
|
pub parts: Option<String>,
|
|
/// 工具调用 ID(role=Tool 时必填)
|
|
pub tool_call_id: Option<String>,
|
|
/// AI 发起的工具调用 JSON(可空)
|
|
pub tool_calls: Option<String>,
|
|
/// 生成该消息的 model(仅 assistant)
|
|
pub model: Option<String>,
|
|
/// 消息状态:active/compressed/archived_segment/truncated(默认 active)
|
|
pub status: String,
|
|
/// DeepSeek thinking 推理内容(可空)
|
|
pub reasoning_content: Option<String>,
|
|
/// 消息创建时间(Unix 毫秒,可空)
|
|
pub timestamp: Option<i64>,
|
|
/// 落库时间字符串(迁移期 fallback 到对话 created_at)
|
|
pub created_at: String,
|
|
}
|
|
|
|
// ============================================================
|
|
// 知识库模型 (V7)
|
|
// ============================================================
|
|
|
|
/// 知识条目记录(经验沉淀基本单元,共享记忆层)
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct KnowledgeRecord {
|
|
pub id: String,
|
|
pub kind: String, // KnowledgeKind snake_case(7 种)
|
|
pub title: String,
|
|
pub content: String,
|
|
pub tags: Option<String>, // JSON 数组字符串
|
|
pub status: String, // candidate|pending_review|published|archived
|
|
pub confidence: Option<String>, // high|medium|low(AI 提炼自评,可空)
|
|
pub reuse_count: i32, // 唯一客观排序信号
|
|
pub verified: bool, // 发布审核时一次性人工标
|
|
pub source_project: Option<String>, // 来源项目(仅溯源不过滤)
|
|
pub source_ref: Option<String>, // 来源实体引用(如 conv:{id})
|
|
pub reasoning: Option<String>, // AI 提炼判断依据("为何值得沉淀"),手动录入为 None
|
|
/// 嵌入生成状态(V23):None/pending=未生成,done=成功,failed=失败可重试。
|
|
///
|
|
/// P1 修复(嵌入失败无标记):spawn_embedding_for_knowledge 此前 fire-and-forget,
|
|
/// provider 临时不可用 → 仅 warn,该条永久无向量索引无人感知。
|
|
/// 现写入 done/failed,failed 可由 knowledge_retry_embedding 触发补偿重试。
|
|
/// `#[serde(default)]` 兼容老前端/老 JSON(未带该字段反序列化为 None)。
|
|
#[serde(default)]
|
|
pub embedding_status: Option<String>,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
/// 知识生命线事件记录(追加型审计:产生/审核/引用/归档)
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct KnowledgeEventRecord {
|
|
pub id: String,
|
|
pub knowledge_id: String,
|
|
pub event_type: String, // created | extracted | status_changed | referenced | archived
|
|
pub source_ref: Option<String>, // 触发来源: conv:{id} / manual / system
|
|
pub context_json: Option<String>, // JSON: 因 event_type 而异
|
|
pub timestamp: String,
|
|
}
|