Skip to content

refactor: Route async task mode through TaskExecutionService (#95)#162

Open
AndriiPasternak31 wants to merge 7 commits intoAbilityai:mainfrom
AndriiPasternak31:AndriiPasternak31/95-async-task-service
Open

refactor: Route async task mode through TaskExecutionService (#95)#162
AndriiPasternak31 wants to merge 7 commits intoAbilityai:mainfrom
AndriiPasternak31:AndriiPasternak31/95-async-task-service

Conversation

@AndriiPasternak31
Copy link
Copy Markdown
Contributor

Summary

  • Replaced inline slot/activity/sanitization/error logic in _execute_task_background() with delegation to TaskExecutionService, matching the pattern used by internal.py and public.py
  • Extracted _save_to_chat_session() helper to eliminate DRY violation between async and sync session persistence paths
  • Net reduction of ~124 lines in chat.py

Changes

  • src/backend/routers/chat.py — Rewrote _execute_task_background() as thin wrapper, simplified async branch, extracted shared helper
  • tests/test_parallel_task.py — Added 5 new tests (session persistence, collaboration activity, safety net)
  • docs/memory/changelog.md — Added changelog entry
  • docs/memory/feature-flows/task-execution-service.md — Updated flow documentation

Test Plan

  • Existing tests pass: pytest tests/test_parallel_task.py -v
  • New tests pass: TestAsyncSessionPersistence, TestAsyncCollaborationActivity, TestAsyncSafetyNet
  • Manual: async task returns immediately and completes via polling
  • Manual: sync task with save_to_session still persists to chat session
  • Manual: agent-to-agent async task completes collaboration activity

Closes #95

Generated with Claude Code

Copy link
Copy Markdown
Contributor

@vybe vybe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clean refactor! The delegation pattern is solid and the 5 new tests are a great addition. A few items before merge:

Required

  • execution_time_ms regression in _save_to_chat_session() — The old _execute_task_background() passed execution_time_ms to db.add_chat_message(). The new helper omits it because TaskExecutionResult has no such field. Async chat sessions will now always store NULL for execution time. Either add execution_time_ms: Optional[int] to TaskExecutionResult and populate it in the service, or explicitly accept this loss and document it.

  • context_used guard dropped — Old: context_used if context_used > 0 else None. New: stores result.context_used directly (could persist 0 instead of NULL). Small behavior change worth preserving for consistency.

  • Please rebase onto main before merge — the branch has a merge commit (merge: resolve changelog conflict with upstream/main) that should be cleaned up.

Minor

  • Issue #95 is missing the type-refactor label.
  • Confirm public.py's _execute_public_chat_background() (line 775) is considered resolved — it appears to already delegate to TaskExecutionService, but the issue's "Files to Change" section lists it. Either close the loop in the PR description or follow up in a separate issue.
  • Add ## Security Considerations section to task-execution-service.md (even a brief "N/A — service layer, no direct auth or user input" is sufficient to satisfy the flow format spec).

Please address the required items and request re-review.

AndriiPasternak31 and others added 5 commits April 11, 2026 01:04
…ai#95)

The async mode path in chat.py duplicated slot management, activity
tracking, credential sanitization, and error handling instead of
delegating to TaskExecutionService. Any fix to the service didn't
apply to async mode, creating two maintenance surfaces.

- Replace _execute_task_background() with thin wrapper delegating to
  TaskExecutionService (matches internal.py pattern)
- Simplify async branch: remove inline slot/activity/status management
- Extract _save_to_chat_session() helper to eliminate DRY violation
  between async and sync session persistence paths
- Add 5 new tests for session persistence, collaboration activity,
  and safety net error handling
- Net reduction of ~124 lines in chat.py

Closes Abilityai#95

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix stringly-typed status comparison: "failed" → TaskExecutionStatus.FAILED
- Remove unused `source` variable (ExecutionSource computed but never used)
- Add try/except to sync path collaboration activity completion (matches async path)
- Extract poll_execution_until_done() test helper, eliminating 5 duplicate polling loops

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…xecutionResult

- Add execution_time_ms field to TaskExecutionResult dataclass and populate
  it in execute_task() so callers (including _save_to_chat_session) can
  persist it to chat messages
- Pass execution_time_ms in _save_to_chat_session() assistant message call
- Update coverage table: async parallel task now uses TaskExecutionService
- Add Security Considerations section to task-execution-service.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AndriiPasternak31 AndriiPasternak31 force-pushed the AndriiPasternak31/95-async-task-service branch from 1d4236f to 2344f31 Compare April 11, 2026 00:06
@AndriiPasternak31
Copy link
Copy Markdown
Contributor Author

Addressed review feedback

Required items

  1. execution_time_ms regression — Fixed. Added execution_time_ms: Optional[int] = None field to TaskExecutionResult dataclass, populated it in execute_task(), and passed it through _save_to_chat_session() to db.add_chat_message(). Async chat sessions will now correctly store execution time.

  2. context_used guard — Verified. The service already applies the context_used if context_used > 0 else None guard (lines 287, 313 in task_execution_service.py) when building TaskExecutionResult, so result.context_used is already None when the raw value is 0. No code change needed.

  3. Rebase onto main — Done. Rebased cleanly onto upstream/main, removed the merge commit. History is now linear with 5 clean commits.

Minor items

  1. Issue Route async task mode through TaskExecutionService #95 type-refactor label — Unable to add (insufficient permissions on upstream). Please add manually.

  2. public.py delegation status — Confirmed. _execute_public_chat_background() (line 699) already delegates to TaskExecutionService via task_execution_service.execute_task(). No follow-up needed.

  3. Security Considerations section — Added to task-execution-service.md: "N/A — service layer, no direct auth or user input. Auth enforced by calling routers."

Additional improvements merged from main

@AndriiPasternak31 AndriiPasternak31 requested a review from vybe April 11, 2026 00:12
AndriiPasternak31 and others added 2 commits April 11, 2026 01:12
The extracted _save_to_chat_session() helper dropped subscription_id
from db.create_new_chat_session(), causing new chat sessions from
both async and sync /task endpoints to have NULL subscription_id.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents test helper from polling for 120s when an execution is
cancelled, which would cause unnecessary test timeouts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Route async task mode through TaskExecutionService

2 participants