MCPcopy
hub / github.com/claude-code-best/claude-code / useTaskListWatcher

Function useTaskListWatcher

src/hooks/useTaskListWatcher.ts:34–189  ·  view source on GitHub ↗
({
  taskListId,
  isLoading,
  onSubmitTask,
}: Props)

Source from the content-addressed store, hash-verified

32 * tasks and processes them one at a time.
33 */
34export function useTaskListWatcher({
35 taskListId,
36 isLoading,
37 onSubmitTask,
38}: Props): void {
39 const currentTaskRef = useRef<string | null>(null)
40 const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
41
42 // Stabilize unstable props via refs so the watcher effect doesn't depend on
43 // them. isLoading flips every turn, and onSubmitTask's identity changes
44 // whenever onQuery's deps change. Without this, the watcher effect re-runs
45 // on every turn, calling watcher.close() + watch() each time — which is a
46 // trigger for Bun's PathWatcherManager deadlock (oven-sh/bun#27469).
47 const isLoadingRef = useRef(isLoading)
48 isLoadingRef.current = isLoading
49 const onSubmitTaskRef = useRef(onSubmitTask)
50 onSubmitTaskRef.current = onSubmitTask
51
52 const enabled = taskListId !== undefined
53 const agentId = taskListId ?? DEFAULT_TASKS_MODE_TASK_LIST_ID
54
55 // checkForTasks reads isLoading and onSubmitTask from refs — always
56 // up-to-date, no stale closure, and doesn't force a new function identity
57 // per render. Stored in a ref so the watcher effect can call it without
58 // depending on it.
59 const checkForTasksRef = useRef<() => Promise<void>>(async () => {})
60 checkForTasksRef.current = async () => {
61 if (!enabled) {
62 return
63 }
64
65 // Don't need to submit new tasks if we are already working
66 if (isLoadingRef.current) {
67 return
68 }
69
70 const tasks = await listTasks(taskListId)
71
72 // If we have a current task, check if it's been resolved
73 if (currentTaskRef.current !== null) {
74 const currentTask = tasks.find(t => t.id === currentTaskRef.current)
75 if (!currentTask || currentTask.status === 'completed') {
76 logForDebugging(
77 `[TaskListWatcher] Task #${currentTaskRef.current} is marked complete, ready for next task`,
78 )
79 currentTaskRef.current = null
80 } else {
81 // Still working on current task
82 return
83 }
84 }
85
86 // Find an open task with no owner that isn't blocked
87 const availableTask = findAvailableTask(tasks)
88
89 if (!availableTask) {
90 return
91 }

Callers 1

REPLFunction · 0.85

Calls 10

listTasksFunction · 0.85
claimTaskFunction · 0.85
updateTaskFunction · 0.85
ensureTasksDirFunction · 0.85
getTasksDirFunction · 0.85
debouncedCheckFunction · 0.85
findAvailableTaskFunction · 0.70
formatTaskAsPromptFunction · 0.70
closeMethod · 0.65
logForDebuggingFunction · 0.50

Tested by

no test coverage detected