|
|
@@ -38,17 +38,19 @@ export interface PlanSummary {
|
|
|
* the first `in_progress` item and counts the remaining active ones, so a
|
|
|
* parallel plan reports how many tasks are running rather than naming one and
|
|
|
* hiding the others. `activeContent` is null when nothing is in progress, or
|
|
|
- * when the first active item carries no usable content — model JSON may. The
|
|
|
- * row then renders the counts alone rather than falling back to the generic
|
|
|
- * tool summary: the counts are already known to be good, and the active-item
|
|
|
- * clause is the only part an unusable name costs.
|
|
|
+ * when the first active item's content is missing, mistyped, or blank once
|
|
|
+ * trimmed — the tool's own rule for usable content, applied here because a
|
|
|
+ * rejected call keeps its args verbatim. The row then renders the counts alone
|
|
|
+ * rather than falling back to the generic tool summary: the counts are already
|
|
|
+ * known to be good, and the active-item clause is the only part an unusable
|
|
|
+ * name costs.
|
|
|
* @param todos - the whole list, in model order.
|
|
|
* @returns the done/total counts and the two summary halves.
|
|
|
*/
|
|
|
export function planSummary(todos: readonly PlanItemLike[]): PlanSummary {
|
|
|
const active = todos.filter(t => t.status === 'in_progress')
|
|
|
const first = active[0]?.content
|
|
|
- const named = typeof first === 'string' && first !== ''
|
|
|
+ const named = typeof first === 'string' && first.trim() !== ''
|
|
|
return {
|
|
|
done: todos.filter(t => t.status === 'completed').length,
|
|
|
total: todos.length,
|