Files
clide/lib/builtin/claude/src/task_list.dart
T
jpmschweitzerandClaude Opus 4.8 6d0ebab721 chore: adopt Dart 3.9 toolchain — honest floor + tall-style reformat (T-353)
Raise the declared minimums in pubspec.yaml to what our deps already
require: Flutter >=3.35.0 / Dart >=3.9.0 (was 3.19.0 / 3.5.0). alchemist
0.12 needs Flutter 3.32; Dart 3.9 first ships in Flutter 3.35, so 3.35 is
the binding floor. Pin the exact build toolchain in .fvmrc (Flutter
3.44.1).

Moving to the Dart 3.9 language level switches `dart format` to the new
"tall" style and enables two new lints. This commit is the resulting
mechanical churn, isolated from any behaviour change:
  - whole-tree `dart format` reformat (tall style)
  - `dart fix` for unnecessary_underscores + use_null_aware_elements

No runtime behaviour change; `make test` green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 12:11:53 +02:00

54 lines
1.8 KiB
Dart

/// Claude's working task list, modelled from the conversation for the docked
/// task view (T-308).
///
/// Claude tracks tasks with the `TodoWrite` tool, which **replaces the whole
/// list** on each call — so the current state is simply the todos of the most
/// recent `TodoWrite`. This is a latest-wins snapshot, not an append log; older
/// `TodoWrite` calls are superseded.
library;
import 'package:clide/builtin/claude/src/transcript_reader.dart';
enum TaskStatus { pending, inProgress, completed }
class TaskItem {
const TaskItem({required this.text, required this.status});
final String text;
final TaskStatus status;
@override
bool operator ==(Object other) => other is TaskItem && other.text == text && other.status == status;
@override
int get hashCode => Object.hash(text, status);
}
/// The current task list — the todos of the most recent `TodoWrite` tool call,
/// or empty if Claude hasn't written one this session.
List<TaskItem> taskListFrom(List<ConversationItem> items) {
for (var i = items.length - 1; i >= 0; i--) {
final it = items[i];
if (it is! AssistantToolUse || it.name != 'TodoWrite') continue;
final raw = it.input['todos'];
if (raw is! List) return const [];
return [
for (final t in raw)
if (t is Map)
TaskItem(
// `content` is the canonical label; `activeForm` is the present-tense
// variant TodoWrite also carries — fall back to it, then to empty.
text: (t['content'] ?? t['activeForm'] ?? '').toString(),
status: _statusFrom(t['status']),
),
];
}
return const [];
}
TaskStatus _statusFrom(Object? raw) => switch (raw) {
'in_progress' => TaskStatus.inProgress,
'completed' => TaskStatus.completed,
_ => TaskStatus.pending,
};