refactor: break up dispatch_task() into helper functions (#1137)
Some checks failed
Tests / lint (pull_request) Successful in 17s
Tests / test (pull_request) Failing after 25m25s

Extract three helpers from the 108-line dispatch_task() function:
- _validate_task() — precondition checks (title required)
- _select_dispatch_strategy() — decides gitea vs api vs local
- _log_dispatch_result() — logging for failed attempts

Main dispatch_task() now orchestrates: validate → resolve → select strategy → dispatch → log/escalate.

Fixes #1137
This commit is contained in:
kimi
2026-03-23 17:43:14 -04:00
parent c5b49d6cff
commit 5b26396206

View File

@@ -686,6 +686,80 @@ async def _dispatch_local(
# ---------------------------------------------------------------------------
def _validate_task(
title: str,
task_type: TaskType | None,
agent: AgentType | None,
issue_number: int | None,
) -> DispatchResult | None:
"""Validate task preconditions.
Args:
title: Task title to validate.
task_type: Optional task type for result construction.
agent: Optional agent for result construction.
issue_number: Optional issue number for result construction.
Returns:
A failed DispatchResult if validation fails, None otherwise.
"""
if not title.strip():
return DispatchResult(
task_type=task_type or TaskType.ROUTINE_CODING,
agent=agent or AgentType.TIMMY,
issue_number=issue_number,
status=DispatchStatus.FAILED,
error="`title` is required.",
)
return None
def _select_dispatch_strategy(agent: AgentType, issue_number: int | None) -> str:
"""Select the dispatch strategy based on agent interface and context.
Args:
agent: The target agent.
issue_number: Optional Gitea issue number.
Returns:
Strategy name: "gitea", "api", or "local".
"""
spec = AGENT_REGISTRY[agent]
if spec.interface == "gitea" and issue_number is not None:
return "gitea"
if spec.interface == "api":
return "api"
return "local"
def _log_dispatch_result(
title: str,
result: DispatchResult,
attempt: int,
max_retries: int,
) -> None:
"""Log the outcome of a dispatch attempt.
Args:
title: Task title for logging context.
result: The dispatch result.
attempt: Current attempt number (0-indexed).
max_retries: Maximum retry attempts allowed.
"""
if result.success:
return
if attempt > 0:
logger.info("Retry %d/%d for task %r", attempt, max_retries, title[:60])
logger.warning(
"Dispatch attempt %d failed for task %r: %s",
attempt + 1,
title[:60],
result.error,
)
async def dispatch_task(
title: str,
description: str = "",
@@ -726,17 +800,13 @@ async def dispatch_task(
if result.success:
print(f"Assigned to {result.agent.value}")
"""
# 1. Validate
validation_error = _validate_task(title, task_type, agent, issue_number)
if validation_error:
return validation_error
# 2. Resolve task type and agent
criteria = acceptance_criteria or []
if not title.strip():
return DispatchResult(
task_type=task_type or TaskType.ROUTINE_CODING,
agent=agent or AgentType.TIMMY,
issue_number=issue_number,
status=DispatchStatus.FAILED,
error="`title` is required.",
)
resolved_type = task_type or infer_task_type(title, description)
resolved_agent = agent or select_agent(resolved_type)
@@ -748,18 +818,16 @@ async def dispatch_task(
issue_number,
)
spec = AGENT_REGISTRY[resolved_agent]
# 3. Select strategy and dispatch with retries
strategy = _select_dispatch_strategy(resolved_agent, issue_number)
last_result: DispatchResult | None = None
for attempt in range(max_retries + 1):
if attempt > 0:
logger.info("Retry %d/%d for task %r", attempt, max_retries, title[:60])
if spec.interface == "gitea" and issue_number is not None:
for attempt in range(max_retries + 1):
if strategy == "gitea":
result = await _dispatch_via_gitea(
resolved_agent, issue_number, title, description, criteria
)
elif spec.interface == "api":
elif strategy == "api":
result = await _dispatch_via_api(
resolved_agent, title, description, criteria, issue_number, api_endpoint
)
@@ -772,14 +840,9 @@ async def dispatch_task(
if result.success:
return result
logger.warning(
"Dispatch attempt %d failed for task %r: %s",
attempt + 1,
title[:60],
result.error,
)
_log_dispatch_result(title, result, attempt, max_retries)
# All attempts exhausted — escalate
# 4. All attempts exhausted — escalate
assert last_result is not None
last_result.status = DispatchStatus.ESCALATED
logger.error(