新增: 无人值守P0任务边界全链
- 任务级授权边界判定与审批旁路单点插桩 - boundary_json 随会话落库(V45 可逆迁移) - 六路非正常终局统一安全停靠与托盘通知 - 每五轮进度事件与会话头部进度条 - 前端边界配置卡侧栏徽标及 UX 校验补齐
This commit is contained in:
@@ -108,6 +108,8 @@ fn ai_conversation_from_row(row: &Row<'_>) -> std::result::Result<AiConversation
|
||||
// origin 列老库经 v44 迁移补建。unwrap_or(None) 兜底(同 message_id v21 模式):
|
||||
// 迁移未跑/极端情况防御,NULL=主会话。
|
||||
origin: row.get("origin").unwrap_or(None),
|
||||
// boundary_json 列老库经 v45 迁移补建。unwrap_or(None) 兜底(NULL=未声明任务边界)。
|
||||
boundary_json: row.get("boundary_json").unwrap_or(None),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -183,24 +185,25 @@ impl_repo!(
|
||||
from_row => |row| ai_conversation_from_row(row),
|
||||
insert => |conn, rec| {
|
||||
conn.execute(
|
||||
"INSERT INTO ai_conversations (id, title, messages, provider_id, model, models, archived, pinned, prompt_tokens, completion_tokens, pinned_goals, pending_approvals, created_at, updated_at, origin)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)",
|
||||
"INSERT INTO ai_conversations (id, title, messages, provider_id, model, models, archived, pinned, prompt_tokens, completion_tokens, pinned_goals, pending_approvals, created_at, updated_at, origin, boundary_json)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16)",
|
||||
params![
|
||||
rec.id, rec.title, rec.messages, rec.provider_id, rec.model, rec.models, rec.archived,
|
||||
if rec.pinned { 1i32 } else { 0i32 },
|
||||
rec.prompt_tokens, rec.completion_tokens,
|
||||
rec.pinned_goals, rec.pending_approvals, rec.created_at, rec.updated_at, rec.origin
|
||||
rec.pinned_goals, rec.pending_approvals, rec.created_at, rec.updated_at, rec.origin,
|
||||
rec.boundary_json
|
||||
],
|
||||
)
|
||||
},
|
||||
update => |conn, rec| {
|
||||
conn.execute(
|
||||
"UPDATE ai_conversations SET title = ?1, messages = ?2, provider_id = ?3, model = ?4, models = ?5, archived = ?6, pinned = ?7, prompt_tokens = ?8, completion_tokens = ?9, pinned_goals = ?10, pending_approvals = ?11, updated_at = ?12 WHERE id = ?13",
|
||||
"UPDATE ai_conversations SET title = ?1, messages = ?2, provider_id = ?3, model = ?4, models = ?5, archived = ?6, pinned = ?7, prompt_tokens = ?8, completion_tokens = ?9, pinned_goals = ?10, pending_approvals = ?11, updated_at = ?12, boundary_json = ?13 WHERE id = ?14",
|
||||
params![
|
||||
rec.title, rec.messages, rec.provider_id, rec.model, rec.models, rec.archived,
|
||||
if rec.pinned { 1i32 } else { 0i32 },
|
||||
rec.prompt_tokens, rec.completion_tokens,
|
||||
rec.pinned_goals, rec.pending_approvals, rec.updated_at, rec.id
|
||||
rec.pinned_goals, rec.pending_approvals, rec.updated_at, rec.boundary_json, rec.id
|
||||
],
|
||||
)
|
||||
}
|
||||
@@ -783,6 +786,29 @@ impl AiConversationRepo {
|
||||
.map_err(storage_err)?
|
||||
}
|
||||
|
||||
/// 无人值守任务边界快照写入(V45 boundary_json 列)。None=清除(回退逐次审批)。
|
||||
///
|
||||
/// 仅改 boundary_json,不动 updated_at(纯元数据标记,对齐 set_archived/set_pinned)。
|
||||
/// 返回 affected>0:对话尚未落库(懒创建,首条消息前)时影响 0 行——调用方以内存
|
||||
/// per_conv.boundary 为真相源,首插 save 会随 INSERT 带上,无需报错。
|
||||
pub async fn set_boundary_json(&self, id: &str, boundary_json: Option<&str>) -> Result<bool> {
|
||||
let conn = self.conn.clone();
|
||||
let id = id.to_owned();
|
||||
let value = boundary_json.map(|s| s.to_owned());
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let guard = conn.blocking_lock();
|
||||
let affected = guard
|
||||
.execute(
|
||||
"UPDATE ai_conversations SET boundary_json = ?1 WHERE id = ?2",
|
||||
params![value, id],
|
||||
)
|
||||
.map_err(storage_err)?;
|
||||
Ok(affected > 0)
|
||||
})
|
||||
.await
|
||||
.map_err(storage_err)?
|
||||
}
|
||||
|
||||
/// G1.3: 删除对话 + 其全部 ai_messages 子行(单事务原子)。
|
||||
///
|
||||
/// 背景:原宏生成 `delete` 只删 ai_conversations 主行,而 ai_messages 表无外键级联
|
||||
|
||||
Reference in New Issue
Block a user