Skip to content

Commit ef38568

Browse files
authored
💄 Todo list tool messages (microsoft#259245)
1 parent 286f5ab commit ef38568

File tree

1 file changed

+50
-8
lines changed

1 file changed

+50
-8
lines changed

src/vs/workbench/contrib/chat/common/tools/manageTodoListTool.ts

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const ManageTodoListToolData: IToolData = {
3232
canBeReferencedInPrompt: true,
3333
icon: ThemeIcon.fromId(Codicon.checklist.id),
3434
displayName: 'Update Todo List',
35+
userDescription: 'Manage and track todo items for task planning',
3536
modelDescription: 'Manage a structured todo list to track progress and plan tasks throughout your coding session. Use this tool VERY frequently to ensure task visibility and proper planning.\n\nWhen to use this tool:\n- Complex multi-step work requiring planning and tracking\n- When user provides multiple tasks or requests (numbered/comma-separated)\n- After receiving new instructions that require multiple steps\n- BEFORE starting work on any todo (mark as in-progress)\n- IMMEDIATELY after completing each todo (mark completed individually)\n- When breaking down larger tasks into smaller actionable steps\n- To give users visibility into your progress and planning\n\nWhen NOT to use:\n- Single, trivial tasks that can be completed in one step\n- Purely conversational/informational requests\n- When just reading files or performing simple searches\n\nCRITICAL workflow:\n1. Plan tasks by writing todo list with specific, actionable items\n2. Mark ONE todo as in-progress before starting work\n3. Complete the work for that specific todo\n4. Mark that todo as completed IMMEDIATELY\n5. Move to next todo and repeat\n\nTodo states:\n- not-started: Todo not yet begun\n- in-progress: Currently working (limit ONE at a time)\n- completed: Finished successfully\n\nIMPORTANT: Mark todos completed as soon as they are done. Do not batch completions.',
3637
source: ToolDataSource.Internal,
3738
inputSchema: {
@@ -164,20 +165,16 @@ export class ManageTodoListTool extends Disposable implements IToolImpl {
164165

165166
const args = context.parameters as IManageTodoListToolInputParams;
166167
let message: string | undefined;
168+
167169
switch (args.operation) {
168170
case 'write': {
169171
if (args.todoList) {
170-
if (!currentTodoItems.length) {
171-
message = 'Creating todo list';
172-
}
173-
else {
174-
message = 'Updating todo list';
175-
}
172+
message = this.generatePastTenseMessage(currentTodoItems, args.todoList);
176173
}
177174
break;
178175
}
179176
case 'read': {
180-
message = 'Reading all items in todo list';
177+
message = 'Read todo list';
181178
break;
182179
}
183180
default:
@@ -193,7 +190,7 @@ export class ManageTodoListTool extends Disposable implements IToolImpl {
193190
}));
194191

195192
return {
196-
invocationMessage: new MarkdownString(message ?? 'Unknown todo list operation'),
193+
pastTenseMessage: new MarkdownString(message ?? 'Updated todo list'),
197194
toolSpecificData: {
198195
kind: 'todoList',
199196
sessionId: context.chatSessionId,
@@ -202,6 +199,51 @@ export class ManageTodoListTool extends Disposable implements IToolImpl {
202199
};
203200
}
204201

202+
private generatePastTenseMessage(currentTodos: IChatTodo[], newTodos: IManageTodoListToolInputParams['todoList']): string {
203+
// If no current todos, this is creating new ones
204+
if (currentTodos.length === 0) {
205+
return `Created ${newTodos.length} todo${newTodos.length === 1 ? '' : 's'}`;
206+
}
207+
208+
// Create map for easier comparison
209+
const currentTodoMap = new Map(currentTodos.map(todo => [todo.id, todo]));
210+
211+
// Check for newly started todos (marked as in-progress) - highest priority
212+
const startedTodos = newTodos.filter(newTodo => {
213+
const currentTodo = currentTodoMap.get(newTodo.id);
214+
return currentTodo && currentTodo.status !== 'in-progress' && newTodo.status === 'in-progress';
215+
});
216+
217+
if (startedTodos.length > 0) {
218+
const startedTodo = startedTodos[0]; // Should only be one in-progress at a time
219+
const totalTodos = newTodos.length;
220+
const currentPosition = newTodos.findIndex(todo => todo.id === startedTodo.id) + 1;
221+
return `Starting (${currentPosition}/${totalTodos}) *${startedTodo.title}*`;
222+
}
223+
224+
// Check for newly completed todos
225+
const completedTodos = newTodos.filter(newTodo => {
226+
const currentTodo = currentTodoMap.get(newTodo.id);
227+
return currentTodo && currentTodo.status !== 'completed' && newTodo.status === 'completed';
228+
});
229+
230+
if (completedTodos.length > 0) {
231+
const completedTodo = completedTodos[0]; // Get the first completed todo for the message
232+
const totalTodos = newTodos.length;
233+
const currentPosition = newTodos.findIndex(todo => todo.id === completedTodo.id) + 1;
234+
return `Completed (${currentPosition}/${totalTodos}) *${completedTodo.title}*`;
235+
}
236+
237+
// Check for new todos added
238+
const addedTodos = newTodos.filter(newTodo => !currentTodoMap.has(newTodo.id));
239+
if (addedTodos.length > 0) {
240+
return `Added ${addedTodos.length} todo${addedTodos.length === 1 ? '' : 's'}`;
241+
}
242+
243+
// Default message for other updates
244+
return 'Updated todo list';
245+
}
246+
205247
private handleRead(storage: IChatTodoListStorage, sessionId: string): string {
206248
const todoItems = storage.getTodoList(sessionId);
207249

0 commit comments

Comments
 (0)