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

Function claimTask

src/utils/tasks.ts:541–612  ·  view source on GitHub ↗
(
  taskListId: string,
  taskId: string,
  claimantAgentId: string,
  options: ClaimTaskOptions = {},
)

Source from the content-addressed store, hash-verified

539 * if the agent owns any other open tasks before claiming.
540 */
541export async function claimTask(
542 taskListId: string,
543 taskId: string,
544 claimantAgentId: string,
545 options: ClaimTaskOptions = {},
546): Promise<ClaimTaskResult> {
547 const taskPath = getTaskPath(taskListId, taskId)
548
549 // Check existence before locking — proper-lockfile.lock throws if the
550 // target file doesn't exist, and we want a clean task_not_found result.
551 const taskBeforeLock = await getTask(taskListId, taskId)
552 if (!taskBeforeLock) {
553 return { success: false, reason: 'task_not_found' }
554 }
555
556 // If we need to check agent busy status, use task-list-level lock
557 // to prevent TOCTOU race conditions
558 if (options.checkAgentBusy) {
559 return claimTaskWithBusyCheck(taskListId, taskId, claimantAgentId)
560 }
561
562 // Otherwise, use task-level lock (original behavior)
563 let release: (() => Promise<void>) | undefined
564 try {
565 // Acquire exclusive lock on the task file
566 release = await lockfile.lock(taskPath, LOCK_OPTIONS)
567
568 // Read current task state
569 const task = await getTask(taskListId, taskId)
570 if (!task) {
571 return { success: false, reason: 'task_not_found' }
572 }
573
574 // Check if already claimed by another agent
575 if (task.owner && task.owner !== claimantAgentId) {
576 return { success: false, reason: 'already_claimed', task }
577 }
578
579 // Check if already resolved
580 if (task.status === 'completed') {
581 return { success: false, reason: 'already_resolved', task }
582 }
583
584 // Check for unresolved blockers (open or in_progress tasks block)
585 const allTasks = await listTasks(taskListId)
586 const unresolvedTaskIds = new Set(
587 allTasks.filter(t => t.status !== 'completed').map(t => t.id),
588 )
589 const blockedByTasks = task.blockedBy.filter(id =>
590 unresolvedTaskIds.has(id),
591 )
592 if (blockedByTasks.length > 0) {
593 return { success: false, reason: 'blocked', task, blockedByTasks }
594 }
595
596 // Claim the task (already holding taskPath lock — use unsafe variant)
597 const updated = await updateTaskUnsafe(taskListId, taskId, {
598 owner: claimantAgentId,

Callers 3

tasks.test.tsFile · 0.90
tryClaimNextTaskFunction · 0.85
useTaskListWatcherFunction · 0.85

Calls 10

getTaskPathFunction · 0.85
getTaskFunction · 0.85
claimTaskWithBusyCheckFunction · 0.85
listTasksFunction · 0.85
updateTaskUnsafeFunction · 0.85
logForDebuggingFunction · 0.70
errorMessageFunction · 0.70
logErrorFunction · 0.70
releaseFunction · 0.50
hasMethod · 0.45

Tested by

no test coverage detected