Skip to content

Conversation

@edlsh
Copy link
Contributor

@edlsh edlsh commented Dec 23, 2025

Summary

Implements Phase 4 of the Background Task Runner plan: Makes TaskTool truly fire-and-forget by returning immediately after enqueueing work to SessionRunner, while maintaining live progress updates in the parent tool part metadata.

PR Stack

This PR is part of a stacked PR series. Please review and merge in order.

PR Branch Description Status
#5996 feat/async-subagent-1-runner SessionRunner abstraction 🔵 Open
#6036 feat/async-subagent-2-background Background job runner with queue and lifecycle events 🔵 Open
#6041 feat/async-subagent-3-centralize Centralize async session work through SessionRunner 🔵 Open
This PR pr4-fire-and-forget-tasktool Fire-and-forget TaskTool 🆕 New

Base: This PR is stacked on top of #6041

Changes

src/tool/tool.ts

  • Add toolPartID?: string to Tool.Context type for post-return metadata updates

src/session/prompt.ts

  • Pass toolPartID when invoking tool.execute() so tools can update their own part after returning

src/tool/task.ts

  • Fire-and-forget execution: Return immediately after enqueueing work to SessionRunner
  • Live progress updates: Subscribe to child session PartUpdated events and update parent tool part metadata via Storage.read + Session.updatePart
  • Final status propagation: Update parent metadata with job status (completed, failed, canceled, timed_out) when background job ends
  • Proper cleanup: Subscribe to all job lifecycle events and clean up listeners/abort handlers
  • Error handling: Log enqueue failures and perform cleanup; log storage read errors with context
  • Accurate tracing: Use ctx.callID (actual tool call ID) instead of ctx.messageID

Behavior Change

Before: TaskTool blocked until child session completed, then returned the full result.

After: TaskTool returns immediately with "Task started in background." and the child session runs asynchronously. Progress is streamed to the parent tool part metadata. Users can click to navigate to the subagent session.

Testing

  • All 30 SessionRunner tests pass
  • Type checker passes (only pre-existing TUI errors remain)

Related

…ation

PR1 of async subagent delegation stack (Issue anomalyco#5887).

This commit introduces the SessionRunner namespace which provides a unified
interface for executing session loops:

- runOnce(): Synchronous execution wrapping SessionPrompt.prompt (implemented)
- runBackground(): Fire-and-forget execution for async delegation (scaffold only)
- Options/RunResult types for future background execution
- State tracking infrastructure for active background runs

No behavior change - this is purely an abstraction layer.

Next: PR2 will implement runBackground() with lifecycle events.
…le events

- Add Job, JobKind, JobStatus, EnqueueOptions schemas
- Add enqueue(), cancel(), get(), list() APIs
- Add lifecycle events (Queued, Started, Completed, Failed, Canceled, TimedOut)
- Add configurable timeout and concurrency via experimental.backgroundTasks
- Fix: queue now restarts after idle (removed stale started flag)
- Fix: dedupe now returns completion promise, not immediate job reference
- Fix circular import by using regular function for runOnce
- Add toolPartID to Tool.Context for post-return metadata updates
- Pass toolPartID from prompt.ts when invoking tool.execute
- TaskTool now returns immediately after enqueueing work to SessionRunner
- Subscribe to child session part updates for live progress in parent metadata
- Update parent metadata with final job status on completion/failure/cancel/timeout
- Handle enqueue failures with logging and proper cleanup
- Use ctx.callID for accurate tool call tracing
@edlsh edlsh force-pushed the pr4-fire-and-forget-tasktool branch from 64d02c9 to c138f7e Compare December 23, 2025 15:59
@edlsh
Copy link
Contributor Author

edlsh commented Dec 23, 2025

Recreating with consistent branch naming (feat/async-subagent-4-tasktool)

@edlsh edlsh closed this Dec 23, 2025
@edlsh edlsh deleted the pr4-fire-and-forget-tasktool branch December 23, 2025 16:10
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.

1 participant