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>
54 lines
1.8 KiB
Dart
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,
|
|
};
|