refactor: extract shared parseMarkdownChecklist function to eliminate code duplication

- Created src/shared/todoParser.ts with the shared parsing logic
- Updated Task.ts to use the shared function
- Updated updateTodoListTool.ts to use the shared function
- This addresses the code duplication issue identified in PR review
This commit is contained in:
hannesrudolph 2025-07-28 18:38:33 -06:00
parent 52a8aa6e10
commit 6b70b5a99f
16 changed files with 309 additions and 52 deletions

View file

@ -354,11 +354,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -367,6 +374,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -251,11 +251,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -264,6 +271,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -354,11 +354,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -367,6 +374,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -403,11 +403,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -416,6 +423,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -359,11 +359,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -372,6 +379,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -354,11 +354,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -367,6 +374,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -407,11 +407,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -420,6 +427,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -354,11 +354,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -367,6 +374,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -442,11 +442,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -455,6 +462,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -354,11 +354,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -367,6 +374,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -407,11 +407,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -420,6 +427,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -403,11 +403,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -416,6 +423,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -354,11 +354,18 @@ Description: This will let you create a new task instance in the chosen mode usi
Parameters:
- mode: (required) The slug of the mode to start the new task in (e.g., "code", "debug", "architect").
- message: (required) The initial user message or instructions for this new task.
- todos: (optional) A markdown checklist of todo items to initialize the new task with. Use the same format as update_todo_list.
Usage:
<new_task>
<mode>your-mode-slug-here</mode>
<message>Your initial instructions here</message>
<todos>
[ ] First todo item
[ ] Second todo item
[x] Completed todo item
[-] In progress todo item
</todos>
</new_task>
Example:
@ -367,6 +374,19 @@ Example:
<message>Implement a new feature for the application.</message>
</new_task>
Example with todos:
<new_task>
<mode>code</mode>
<message>Implement user authentication</message>
<todos>
[ ] Set up authentication middleware
[ ] Create login endpoint
[ ] Create logout endpoint
[ ] Add session management
[ ] Write tests for authentication
</todos>
</new_task>
## update_todo_list

View file

@ -92,6 +92,7 @@ import { ApiMessage } from "../task-persistence/apiMessages"
import { getMessagesSinceLastSummary, summarizeConversation } from "../condense"
import { maybeRemoveImageBlocks } from "../../api/transform/image-cleaning"
import { restoreTodoListForTask } from "../tools/updateTodoListTool"
import { parseMarkdownChecklist } from "../../shared/todoParser"
// Constants
const MAX_EXPONENTIAL_BACKOFF_SECONDS = 600 // 10 minutes
@ -1970,35 +1971,11 @@ export class Task extends EventEmitter<ClineEvents> {
return
}
this.todoList = []
if (!todosMarkdown) {
this.todoList = []
return
}
const lines = todosMarkdown
.split(/\r?\n/)
.map((l) => l.trim())
.filter(Boolean)
for (const line of lines) {
const match = line.match(/^\[\s*([ xX\-~])\s*\]\s+(.+)$/)
if (!match) continue
let status: "pending" | "in_progress" | "completed" = "pending"
if (match[1] === "x" || match[1] === "X") status = "completed"
else if (match[1] === "-" || match[1] === "~") status = "in_progress"
const id = crypto
.createHash("md5")
.update(match[2] + status)
.digest("hex")
this.todoList.push({
id,
content: match[2],
status,
})
}
this.todoList = parseMarkdownChecklist(todosMarkdown)
}
}

View file

@ -6,6 +6,7 @@ import cloneDeep from "clone-deep"
import crypto from "crypto"
import { TodoItem, TodoStatus, todoStatusSchema } from "@roo-code/types"
import { getLatestTodo } from "../../shared/todo"
import { parseMarkdownChecklist } from "../../shared/todoParser"
let approvedTodoList: TodoItem[] | undefined = undefined
@ -100,32 +101,6 @@ function normalizeStatus(status: string | undefined): TodoStatus {
return "pending"
}
function parseMarkdownChecklist(md: string): TodoItem[] {
if (typeof md !== "string") return []
const lines = md
.split(/\r?\n/)
.map((l) => l.trim())
.filter(Boolean)
const todos: TodoItem[] = []
for (const line of lines) {
const match = line.match(/^\[\s*([ xX\-~])\s*\]\s+(.+)$/)
if (!match) continue
let status: TodoStatus = "pending"
if (match[1] === "x" || match[1] === "X") status = "completed"
else if (match[1] === "-" || match[1] === "~") status = "in_progress"
const id = crypto
.createHash("md5")
.update(match[2] + status)
.digest("hex")
todos.push({
id,
content: match[2],
status,
})
}
return todos
}
export function setPendingTodoList(todos: TodoItem[]) {
approvedTodoList = todos
}

45
src/shared/todoParser.ts Normal file
View file

@ -0,0 +1,45 @@
import crypto from "crypto"
import { TodoItem, TodoStatus } from "@roo-code/types"
/**
* Parse a markdown checklist into TodoItem array.
* Supports the following formats:
* - [ ] for pending items
* - [x] or [X] for completed items
* - [-] or [~] for in-progress items
*
* @param md Markdown checklist string
* @returns Array of TodoItem objects
*/
export function parseMarkdownChecklist(md: string): TodoItem[] {
if (typeof md !== "string") return []
const lines = md
.split(/\r?\n/)
.map((l) => l.trim())
.filter(Boolean)
const todos: TodoItem[] = []
for (const line of lines) {
const match = line.match(/^\[\s*([ xX\-~])\s*\]\s+(.+)$/)
if (!match) continue
let status: TodoStatus = "pending"
if (match[1] === "x" || match[1] === "X") status = "completed"
else if (match[1] === "-" || match[1] === "~") status = "in_progress"
const id = crypto
.createHash("md5")
.update(match[2] + status)
.digest("hex")
todos.push({
id,
content: match[2],
status,
})
}
return todos
}