1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//! Todo 卡片 CLI 显示模块
//!
//! 本模块提供 CLI 转录界面中待办事项(Todo)卡片的解析与显示支持。
//! 主要功能包括:
//! - 工具徽章的颜色映射(为不同类型工具分配可区分的显示颜色)
//! - 待办事项状态符号的转换
//! - 从 JSON 数据中解析待办事项列表
//!
//! 该模块与 `ratatui` 库集成,用于终端 UI 的样式渲染。
use crate;
use Color;
/// 根据工具名称返回 CLI 显示用的徽章文本与颜色
///
/// 该函数将工具名称映射到简短的徽章标识符和对应的颜色,
/// 以便在 CLI 界面中快速区分不同类型的工具调用。
///
/// # 参数
///
/// * `tool_name` - 工具名称字符串,如 "read"、"bash"、"todowrite" 等
///
/// # 返回值
///
/// 返回一个元组,包含:
/// - `&'static str`: 徽章文本标识(如 "[R]"、"[B]" 等)
/// - `Color`: 对应的 `ratatui` 颜色值
///
/// # 映射规则
///
/// | 工具类型 | 徽章 | 颜色 |
/// |---------|------|------|
/// | 文件读取 (`read`) | [R] | 绿色 |
/// | 文件编辑 (`write`, `apply_patch`) | [E] | 黄色 |
/// | 搜索类 (`grep`, `glob`, `lsp`,含旧别名) | [S] | 蓝色 |
/// | Shell 执行 (`bash`) | [B] | 洋红色 |
/// | 待办管理 (`todowrite`, `todoread`) | [T] | 青色 |
/// | 其他未知工具 | [U] | 深灰色 |
///
/// # 示例
///
/// ```ignore
/// let (badge, color) = tool_badge_cli("bash");
/// assert_eq!(badge, "[B]");
/// assert_eq!(color, Color::Magenta);
///
/// let (badge, color) = tool_badge_cli("unknown_tool");
/// assert_eq!(badge, "[U]");
/// ```
pub
/// 将待办事项状态转换为显示符号
///
/// 该函数将待办事项的状态字符串映射为简洁的 Unicode 符号,
/// 用于在 CLI 界面中以视觉方式表示任务进度。
///
/// # 参数
///
/// * `status` - 状态字符串,预期值为 "completed"、"in_progress" 或其他
///
/// # 返回值
///
/// - `"✓"` - 已完成状态(`completed`)
/// - `"·"` - 进行中状态(`in_progress`)
/// - `"○"` - 其他状态(通常为待处理 `pending`)
///
/// # 示例
///
/// ```ignore
/// assert_eq!(todo_status_symbol("completed"), "✓");
/// assert_eq!(todo_status_symbol("in_progress"), "·");
/// assert_eq!(todo_status_symbol("pending"), "○");
/// assert_eq!(todo_status_symbol("cancelled"), "○");
/// ```
pub
/// 待办事项卡片数据结构
///
/// 该结构体存储待办事项列表的汇总统计信息和详细条目,
/// 用于在 CLI 转录界面中渲染待办事项卡片。
///
/// # 字段说明
///
/// * `total` - 待办事项总数
/// * `done` - 已完成事项数量
/// * `running` - 进行中事项数量
/// * `pending` - 待处理事项数量
/// * `items` - 待办事项详情列表,每项包含 (状态, 内容) 元组
///
/// # 不变性
///
/// - `total` 应等于 `done + running + pending`
/// - 所有计数字段应使用 `saturating_add` 进行累加以避免溢出
pub
/// 从 JSON 数组解析待办事项列表
///
/// 该函数遍历 JSON 数组中的每个元素,提取状态和内容字段,
/// 并统计各状态类别的数量。
///
/// # 参数
///
/// * `arr` - JSON 值数组,每个元素应包含 `status` 和 `content` 字段
///
/// # 返回值
///
/// 返回填充完成的 `TodoCardData` 实例,包含:
/// - 各状态的计数统计
/// - 所有待办事项的 (状态, 内容) 列表
///
/// # 容错处理
///
/// - 若 `status` 字段缺失或非字符串,默认使用 "pending"
/// - 若 `content` 字段缺失或非字符串,默认使用 "(empty)"
/// - 对字符串值执行 `trim()` 以去除首尾空白
/// - 所有计数使用 `saturating_add` 防止溢出
///
/// # 示例
///
/// ```ignore
/// use serde_json::json;
///
/// let arr = vec![
/// json!({"status": "completed", "content": "Task 1"}),
/// json!({"status": "in_progress", "content": "Task 2"}),
/// ];
/// let data = parse_todos_from_array(&arr);
/// assert_eq!(data.total, 2);
/// assert_eq!(data.done, 1);
/// assert_eq!(data.running, 1);
/// ```
pub
/// 从 JSON 值或 JSON 字符串中解析出 JSON 值
///
/// 该函数处理两种可能的输入格式:
/// 1. 直接的 JSON 字符串:尝试将其解析为 JSON 值
/// 2. 已经是 JSON 值:直接克隆返回
///
/// # 参数
///
/// * `v` - 待解析的 JSON 值引用
///
/// # 返回值
///
/// - `Some(JsonValue)` - 解析成功,返回 JSON 值
/// - `None` - 输入为字符串但解析失败(无效 JSON)
///
/// # 使用场景
///
/// 该函数用于处理 API 响应中可能出现的双重编码情况,
/// 即 JSON 字符串被再次序列化为 JSON 字符串的场景。
///
/// # 示例
///
/// ```ignore
/// use serde_json::json;
///
/// // 字符串形式的 JSON
/// let v = json!("[{\"status\": \"completed\"}]");
/// let parsed = parse_json_from_value_or_json_string(&v);
/// assert!(parsed.is_some());
///
/// // 直接的 JSON 对象
/// let v = json!({"key": "value"});
/// let parsed = parse_json_from_value_or_json_string(&v);
/// assert!(parsed.is_some());
/// ```
pub
/// 解析 `todowrite` 工具调用的卡片数据
///
/// 该函数从 `todowrite` 工具的原始 JSON 输入字符串中提取待办事项列表。
/// 支持处理输入字段可能是 JSON 字符串的情况(双重编码)。
///
/// # 参数
///
/// * `input_raw` - 原始 JSON 字符串,预期结构为 `{"input": {"todos": [...]}}` 或
/// `{"input": "{...JSON字符串...}"}`
///
/// # 返回值
///
/// - `Some(TodoCardData)` - 解析成功,返回待办事项数据
/// - `None` - 解析失败(JSON 格式错误、缺少必要字段、类型不匹配等)
///
/// # JSON 结构期望
///
/// ```json
/// {
/// "input": {
/// "todos": [
/// {"status": "completed", "content": "完成任务A"},
/// {"status": "in_progress", "content": "执行任务B"}
/// ]
/// }
/// }
/// ```
///
/// # 示例
///
/// ```ignore
/// use serde_json::json;
///
/// let input = json!({
/// "input": {
/// "todos": [
/// {"status": "completed", "content": "Task 1"}
/// ]
/// }
/// }).to_string();
///
/// let data = parse_todowrite_card_data(&input);
/// assert!(data.is_some());
/// assert_eq!(data.unwrap().done, 1);
/// ```
pub
/// 解析 `todoread` 工具调用的卡片数据
///
/// 该函数从 `todoread` 工具的原始 JSON 输出字符串中提取待办事项列表。
/// 与 `parse_todowrite_card_data` 不同,此函数从 `output` 字段读取数据。
///
/// # 参数
///
/// * `input_raw` - 原始 JSON 字符串,预期结构为 `{"output": [...]}` 或
/// `{"output": "[...JSON字符串...]"}`
///
/// # 返回值
///
/// - `Some(TodoCardData)` - 解析成功,返回待办事项数据
/// - `None` - 解析失败(JSON 格式错误、缺少必要字段、类型不匹配等)
///
/// # JSON 结构期望
///
/// ```json
/// {
/// "output": [
/// {"status": "completed", "content": "完成任务A"},
/// {"status": "pending", "content": "待完成任务B"}
/// ]
/// }
/// ```
///
/// # 容错处理
///
/// - 支持 `output` 字段直接为数组
/// - 支持 `output` 字段为 JSON 字符串(需进一步解析)
/// - 自动去除字符串首尾空白
///
/// # 示例
///
/// ```ignore
/// use serde_json::json;
///
/// let input = json!({
/// "output": [
/// {"status": "completed", "content": "Task 1"},
/// {"status": "pending", "content": "Task 2"}
/// ]
/// }).to_string();
///
/// let data = parse_todoread_card_data(&input);
/// assert!(data.is_some());
/// let data = data.unwrap();
/// assert_eq!(data.total, 2);
/// assert_eq!(data.done, 1);
/// assert_eq!(data.pending, 1);
/// ```
pub