Skip to content

Commit

Permalink
feat: include checklists
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasn committed Jan 23, 2025
1 parent 2904a00 commit b32de55
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 15 deletions.
88 changes: 79 additions & 9 deletions lib/features/ai/state/ollama_task_summary.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:langchain/langchain.dart';
import 'package:langchain_ollama/langchain_ollama.dart';
import 'package:lotti/classes/journal_entities.dart';
import 'package:lotti/database/database.dart';
import 'package:lotti/features/journal/util/entry_tools.dart';
import 'package:lotti/get_it.dart';
import 'package:lotti/services/entities_cache_service.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
Expand Down Expand Up @@ -35,12 +36,12 @@ class AiTaskSummaryController extends _$AiTaskSummaryController {
temperature: 3,
system: 'The prompt is a markdown document describing a task, '
'with logbook of the completion of the task. '
'Summarize the task, the achieved results, and the remaining steps. '
'Also give me summary of the learnings, if there are any, and '
'anything else that might be relevant to the task. '
'Keep it short and succinct. '
'Be slightly motivational, but not overly so. The goal is to get me '
'to finish the task.',
'Also, there might be checklist items with a status of either '
'COMPLETED or TO DO. '
'Summarize the task, the achieved results, and the remaining steps '
'that have not been completed yet. '
'Note that the logbook is in reverse chronological order. '
'Keep it short and succinct. ',
),
);

Expand All @@ -51,8 +52,6 @@ class AiTaskSummaryController extends _$AiTaskSummaryController {
buffer.write(res.outputAsString);
state = buffer.toString();
});

//print(buffer);
}
}

Expand All @@ -71,6 +70,13 @@ class TaskMarkdownController extends _$TaskMarkdownController {

buffer.writeln(entry.getMarkdown());

if (entry is Task) {
await addChecklistSection(
entry,
buffer: buffer,
);
}

final linkedEntities = await _db.getLinkedEntities(id);

for (final linked in linkedEntities) {
Expand All @@ -81,13 +87,69 @@ class TaskMarkdownController extends _$TaskMarkdownController {

return buffer.toString();
}

Future<void> addChecklistSection(
Task task, {
required StringBuffer buffer,
}) async {
final checklistIds = task.data.checklistIds ?? [];

if (checklistIds.isEmpty) {
return;
}

buffer
..writeln('******')
..writeln('Checklists:')
..writeln();

for (final checklistId in checklistIds) {
final checklist = await _db.journalEntityById(checklistId);
if (checklist != null && checklist is Checklist) {
buffer
..writeln(checklist.data.title)
..writeln();

final checklistItemIds = checklist.data.linkedChecklistItems;
for (final checklistItemId in checklistItemIds) {
final checklistItem = await _db.journalEntityById(checklistItemId);
if (checklistItem != null && checklistItem is ChecklistItem) {
final data = checklistItem.data;
buffer
..writeln(
'${data.isChecked ? 'COMPLETED' : 'TO DO'}: ${data.title}',
)
..writeln();
}
}
buffer.writeln();
}
}

buffer
..writeln('******')
..writeln()
..writeln();
}
}

extension EntryExtension on JournalEntity {
String getMarkdown({int indentation = 0}) {
final headline = maybeMap(
event: (event) => 'Event: ${event.data.title}',
task: (task) => 'Task: ${task.data.title}',
task: (task) {
final status = task.data.status.map(
open: (_) => 'OPEN',
groomed: (_) => 'GROOMED',
started: (_) => 'STARTED',
inProgress: (_) => 'IN PROGRESS',
blocked: (_) => 'BLOCKED',
onHold: (_) => 'ON HOLD',
done: (_) => 'DONE',
rejected: (_) => 'REJECTED',
);
return 'Task: ${task.data.title} - Status: $status';
},
orElse: () => null,
);

Expand Down Expand Up @@ -118,6 +180,14 @@ extension EntryExtension on JournalEntity {
..writeln('Date: $formattedDate')
..writeln();

final duration = entryDuration(this);

if (duration.inSeconds > 10) {
buffer
..writeln('Time spent: ${formatDuration(duration)}')
..writeln();
}

if (categoryId != null) {
final category =
getIt<EntitiesCacheService>().getCategoryById(categoryId);
Expand Down
4 changes: 2 additions & 2 deletions lib/features/ai/state/ollama_task_summary.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class AiTaskSummaryListTile extends ConsumerWidget {
leading: const Icon(Icons.chat_rounded),
title: Text(context.messages.aiAssistantSummarizeTask),
onTap: () {
Navigator.of(context).pop();
showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
Expand Down
13 changes: 10 additions & 3 deletions lib/features/ai/ui/task_summary/ai_task_summary_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class AiTaskSummaryView extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
const showInput = false;
final markdown =
ref.watch(taskMarkdownControllerProvider(id: id)).valueOrNull;
final summary = ref.watch(aiTaskSummaryControllerProvider(id: id));
Expand All @@ -23,10 +24,16 @@ class AiTaskSummaryView extends ConsumerWidget {
child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 600),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MarkdownBody(data: summary),
const SizedBox(height: 200),
if (markdown != null) MarkdownBody(data: markdown),
MarkdownBody(
data: summary,
),
// ignore: dead_code
if (showInput) ...[
const SizedBox(height: 200),
if (markdown != null) MarkdownBody(data: markdown),
],
],
),
),
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: lotti
description: Achieve your goals and keep your data private with Lotti.
publish_to: 'none'
version: 0.9.563+2847
version: 0.9.563+2848

msix_config:
display_name: LottiApp
Expand Down

0 comments on commit b32de55

Please sign in to comment.