Skip to content

fix(task): mark interrupted tool calls as errors in persisted history - #1323

Open
easonLiangWorldedtech wants to merge 1 commit into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:fix/issue-1283-interrupted-tool-results
Open

fix(task): mark interrupted tool calls as errors in persisted history#1323
easonLiangWorldedtech wants to merge 1 commit into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:fix/issue-1283-interrupted-tool-results

Conversation

@easonLiangWorldedtech

@easonLiangWorldedtech easonLiangWorldedtech commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Related GitHub Issue

Closes #1283

Description

When a task is interrupted while an assistant turn's tool calls (e.g. an unconfirmed attempt_completion) are still unanswered, resumeTaskFromHistory synthesizes tool_result blocks so the persisted API conversation stays valid. Those synthetic blocks did not carry is_error: true, so the persisted api_conversation_history.json ended with a success-looking completion while the task list recorded the task as interrupted — and the parent stayed delegated. Any consumer that infers completion from the history (imports, tooling, future delegation logic) was fooled into thinking the task finished.

This fix sets is_error: true on the two synthetic tool_result sites in Task.resumeTaskFromHistory:

  • assistant-last case: tool results synthesized for every tool_use in the final assistant turn,
  • missing-results case: results synthesized for tool_use blocks the final user turn did not answer.

This matches the existing error tool_result pattern already used for new_task truncation in the same file, so the task-list status and the persisted conversation now agree.

Test Procedure

Added two regression tests in src/core/task/__tests__/Task.persistence.spec.ts (describe: "resumeTaskFromHistory interrupted tool calls"). Both spy on initiateTaskLoop to stop the flow right before the agentic loop, feed a persisted history that ends mid-tool-call with initialStatus: "interrupted", and assert the synthetic tool_result blocks passed to the loop carry is_error: true with the correct tool_use_id (the second test also asserts a pre-existing partial result is preserved untouched).

cd src
pnpm exec vitest run core/task/__tests__/Task.persistence.spec.ts   # 15/15 passing (13 pre-existing + 2 new)
pnpm exec eslint --prune-suppressions --max-warnings=0 core/task/Task.ts core/task/__tests__/Task.persistence.spec.ts   # clean, no suppression count changes
pnpm check-types   # 11/11 packages passing

No manual testing required: the change only alters metadata on persisted history and is fully covered by unit tests. No UI changes, so no visual snapshot needed.

Pre-Submission Checklist

  • Issue Linked: This PR is linked to an approved GitHub Issue (see "Related GitHub Issue" above).
  • Scope: My changes are focused on the linked issue (one major feature/fix per PR).
  • Self-Review: I have performed a thorough self-review of my code.
  • Testing: New and/or updated tests have been added to cover my changes (see "Test Procedure").
  • Visual Snapshot (UI changes only): N/A — no UI changes.
  • Documentation Impact: No documentation updates are required.
  • Contribution Guidelines: I have read and agree to the Contributor Guidelines.

Get in Touch

easonLiangWorldedtech

Summary by CodeRabbit

  • Bug Fixes

    • Interrupted tool calls now correctly appear as errors when a task resumes.
    • Existing tool results and interruption details remain unchanged.
  • Tests

    • Added coverage for task recovery in multiple conversation-history scenarios.

When a task is interrupted while an assistant turn's tool calls (e.g. attempt_completion) are unanswered, resumeTaskFromHistory synthesizes tool_result blocks to keep the API conversation valid. Those synthetic blocks lacked is_error: true, so the persisted api_conversation_history.json ends with a success-looking completion while the task list records the task as interrupted - any consumer inferring completion from history is fooled.

Set is_error: true on both synthetic tool_result sites (assistant-last and missing-results cases), matching the existing error tool_result pattern used for new_task truncation. Adds two regression tests covering both code paths.
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 80119019-430c-4b15-a611-acf26181ad60

📥 Commits

Reviewing files that changed from the base of the PR and between 871bb98 and 81c7be9.

📒 Files selected for processing (2)
  • src/core/task/Task.ts
  • src/core/task/__tests__/Task.persistence.spec.ts

Included review availability: Your plan provides up to 4 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

Task resumption now marks synthetic tool_result blocks for incomplete tool calls with is_error: true in both recovery paths. Persistence tests cover these results and confirm that existing tool results remain unchanged.

Changes

Task resumption

Layer / File(s) Summary
Mark synthesized results as errors
src/core/task/Task.ts
Both assistant-last and user-last history recovery paths set is_error: true on synthesized interruption results.
Validate interrupted history recovery
src/core/task/__tests__/Task.persistence.spec.ts
Tests cover unanswered tool calls, preserve existing results, and update typing for Anthropic content blocks.

Estimated code review effort: 2 (Simple) | ~15 minutes

Merge Risk: ⚪ Minimal · up to 81c7b

This localized change marks synthesized interrupted tool results as errors and includes regression coverage; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: edelauna

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #1283 by marking synthetic interrupted tool results as errors in both recovery paths and adding regression tests.
Out of Scope Changes check ✅ Passed The changes are limited to Task history recovery and related persistence tests, with no unrelated code changes.
Title check ✅ Passed The title clearly and concisely describes the main fix: marking interrupted tool calls as errors in persisted history.
Description check ✅ Passed The description explains the issue, implementation, tests, checklist, and documentation impact, with sufficient detail for review.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot added the awaiting-review PR changes are ready and waiting for maintainer re-review label Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR changes are ready and waiting for maintainer re-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Interrupted subtask leaves a success-looking attempt_completion in conversation history

2 participants