refactor(todo): 重构待办事项管理逻辑及更新状态规则

- 移除 TodoItem 中的 priority、created_at 和 updated_at 字段
- 强制每个任务都必须有唯一 id,且由用户负责生成
- 修改合并模式逻辑,merge=true 下保留未提及的旧任务
- 支持已完成和已取消任务重新激活(状态改回 pending 或 in_progress)
- 禁止 in_progress 状态退回到 pending,必须标记为 completed 或 cancelled
- 优化状态转换校验,允许特定状态间合法切换
- 简化任务变更消息,移除详细的新增/更新/移除统计
- 更新文档和示例,明确 id 必须由用户生成和使用
- 修复和补充测试,增强状态转换和合并模式验证
- 调整任务时间戳生成逻辑,统一使用当前时间及索引
- 该变更提供更合理的任务状态机械及管理模式,提升稳定性和易用性
This commit is contained in:
ooodc 2026-06-13 09:22:33 +08:00
parent 02172b6065
commit 229221aab1
6 changed files with 280 additions and 454 deletions

View File

@ -76,9 +76,6 @@ impl CommandHandler for ListTodosCommandHandler {
id: r.id,
content: r.content,
status: r.status,
priority: r.priority,
created_at: r.created_at,
updated_at: r.updated_at,
})
.collect();

View File

@ -141,9 +141,15 @@ impl BusToolCallEmitter {
let topic_id = self.metadata.get("topic_id").filter(|t| !t.is_empty()).cloned();
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs() as i64;
let records: Vec<crate::storage::TodoRecord> = todos_array
.iter()
.filter_map(|item| {
.enumerate()
.filter_map(|(idx, item)| {
Some(crate::storage::TodoRecord {
id: item.get("id")?.as_str()?.to_string(),
scope_key: scope_key.clone(),
@ -151,9 +157,9 @@ impl BusToolCallEmitter {
topic_id: topic_id.clone(),
content: item.get("content")?.as_str()?.to_string(),
status: item.get("status")?.as_str()?.to_string(),
priority: item.get("priority")?.as_str()?.to_string(),
created_at: item.get("created_at")?.as_i64()?,
updated_at: item.get("updated_at")?.as_i64()?,
priority: "medium".to_string(),
created_at: now + idx as i64,
updated_at: now,
})
})
.collect();

View File

@ -28,7 +28,7 @@ const TODO_WRITE_INSTRUCTIONS: &str = r#"
### merge
- `merge: false` todo
- `merge: true` **使 merge=true id**
- `merge: true` **使 merge=true**
###
- `pending`
@ -39,33 +39,34 @@ const TODO_WRITE_INSTRUCTIONS: &str = r#"
###
1. `in_progress`
2. `in_progress`
3. `completed` `cancelled`
4. completed
5. `content`
6. ** `id`** id idid todo_write `current_todos`
3. `completed` `cancelled` `in_progress` `pending`
4. `in_progress` 退 `pending` `completed` `cancelled`
5. completed
6. `content`
7. ** `id`** id `"r9Tg8Kq2"`使 idid todo_write `current_todos`
### 使
pending in_progress id
id
```json
{"merge": true, "todos": [{"content": "修复登录 bug", "status": "in_progress"}]}
{"merge": true, "todos": [{"id": "aB3kLm9x", "content": "修复登录 bug", "status": "in_progress"}]}
```
```json
{"merge": true, "todos": [{"content": "补充测试", "status": "pending"}]}
{"merge": true, "todos": [{"id": "pQ7nWy2z", "content": "补充测试", "status": "pending"}]}
```
** id** current_todos
使 id
```json
{"merge": true, "todos": [{"id": "abc-123", "content": "修复登录 bug", "status": "completed"}]}
{"merge": true, "todos": [{"id": "aB3kLm9x", "content": "修复登录 bug", "status": "completed"}]}
```
```json
{"merge": true, "todos": [
{"id": "abc-123", "content": "修复登录 bug", "status": "completed"},
{"content": "代码审查", "status": "in_progress"}
{"id": "aB3kLm9x", "content": "修复登录 bug", "status": "completed"},
{"id": "pQ7nWy2z", "content": "补充测试", "status": "in_progress"}
]}
```
"#;

View File

@ -88,9 +88,6 @@ pub struct TodoItemSummary {
pub id: String,
pub content: String,
pub status: String,
pub priority: String,
pub created_at: i64,
pub updated_at: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]

View File

@ -57,20 +57,20 @@ impl Default for InMemoryTaskRepository {
#[async_trait]
impl TaskRepository for InMemoryTaskRepository {
async fn save_task_session(&self, session: &TaskSession) -> Result<(), StorageError> {
tracing::warn!(
tracing::debug!(
task_id = %session.id,
session_id = %session.session_id,
state = ?session.state,
"REPO_SAVE: Saving task session"
"Saving task session"
);
self.sessions
.write()
.unwrap()
.insert(session.id.clone(), session.clone());
tracing::warn!(
tracing::debug!(
task_id = %session.id,
total_tasks = self.sessions.read().unwrap().len(),
"REPO_SAVE: Task session saved, current repository size"
"Task session saved, current repository size"
);
Ok(())
}
@ -79,11 +79,11 @@ impl TaskRepository for InMemoryTaskRepository {
let sessions = self.sessions.read().unwrap();
let total = sessions.len();
let keys: Vec<&str> = sessions.keys().map(|k| k.as_str()).collect();
tracing::warn!(
tracing::debug!(
lookup_task_id = %task_id,
total_tasks = total,
all_keys = ?keys,
"REPO_LOOKUP: Looking up task session"
"Looking up task session"
);
Ok(sessions.get(task_id).cloned())
}

File diff suppressed because it is too large Load Diff