Skip to content

test: cover api conversation edge cases#68

Open
doctarock wants to merge 7 commits into
Zoo-Code-Org:mainfrom
doctarock:codex/pr-27-api-conversation-edge-tests
Open

test: cover api conversation edge cases#68
doctarock wants to merge 7 commits into
Zoo-Code-Org:mainfrom
doctarock:codex/pr-27-api-conversation-edge-tests

Conversation

@doctarock
Copy link
Copy Markdown

@doctarock doctarock commented May 11, 2026

Adds the two prepareApiConversationMessage edge-case tests requested during review of #27:

  • Anthropic reasoning without getThoughtSignature falls back to a generic reasoning block
  • User tool_result content is converted to text when the last effective history message is not an assistant

Validation:

  • corepack pnpm --dir src exec vitest run core/task/__tests__/apiConversationHistory.spec.ts
  • corepack pnpm --dir src check-types

Note: this branch is based on doctarock:issue-8-monolith-refactor, so it contains the PR #27 stack plus these additional tests.

Summary by CodeRabbit

Release Notes

  • Refactor

    • Reorganized internal message handling and operation tracking by extracting logic into dedicated modules to improve code maintainability and separation of concerns.
    • Enhanced operation management with improved lifecycle control and automatic cleanup mechanisms.
  • Tests

    • Added comprehensive test suites for message processing workflows including different message type handling and reasoning scenarios.
    • Added tests for operation tracking functionality including timeout behavior, state management, and data integrity.

Review Change Stack

@doctarock doctarock requested a review from hannesrudolph as a code owner May 11, 2026 03:25
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

This PR extracts two independent concerns: API conversation message preparation and pending edit operation management. The first refactoring moves reasoning/thinking block injection and tool_result validation into a dedicated prepareApiConversationMessage module, reducing Task.ts complexity. The second refactoring centralizes timeout lifecycle and state tracking for pending edit operations into PendingEditOperationStore, simplifying ClineProvider.

Changes

API Conversation Message Preparation

Layer / File(s) Summary
Message Preparation Module & Types
src/core/task/apiConversationHistory.ts
New module exports prepareApiConversationMessage with types for API handler detection and message preparation options.
Assistant Message Preparation
src/core/task/apiConversationHistory.ts
prepareAssistantMessage enriches assistant messages with reasoning/thinking blocks and thought signatures based on detected API protocol (Anthropic vs. other providers).
User Message Preparation & Helpers
src/core/task/apiConversationHistory.ts
prepareUserMessage validates and normalizes tool_result blocks, converts them to text when the last effective message is not an assistant, and provides prependContentBlock/appendContentBlock helpers for content manipulation.
Task Integration
src/core/task/Task.ts
addToApiConversationHistory() now delegates message construction to prepareApiConversationMessage instead of performing inline normalization.
Message Preparation Tests
src/core/task/__tests__/apiConversationHistory.spec.ts
Vitest suite validates Anthropic thinking blocks, generic/encrypted reasoning blocks, non-Anthropic protocol handling, and user tool_result normalization with deterministic fake timers.

Pending Edit Operation Store

Layer / File(s) Summary
Pending Edit Operation Store
src/core/webview/PendingEditOperationStore.ts
New PendingEditOperationStore class manages pending edit operations by operationId with automatic timeout cleanup, logging, and deep-copy protection for stored images.
ClineProvider Integration
src/core/webview/ClineProvider.ts
Replaces in-class Map-based pending-operation tracking with delegation to pendingEditOperations store; removes local timeout management and PendingEditOperation interface.
Store Tests
src/core/webview/__tests__/PendingEditOperationStore.spec.ts
Vitest suite validates set(), get(), clear(), clearAll() operations, automatic timeout clearing, image immutability, and logging behavior.

🐰 Two neat refactorings hop into place,
Extraction makes the codebase clean,
With conversation blocks and edits stored,
The logic flows as it was meant to be seen.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding test coverage for API conversation edge cases, which matches the file additions and test suite enhancements in the changeset.
Description check ✅ Passed The description addresses the template's core requirements by identifying the linked issue and explaining implementation details, but omits several important checklist items and structured sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/core/task/__tests__/apiConversationHistory.spec.ts (1)

103-121: 💤 Low value

Consider asserting the conversion is skipped when validation applies.

This test already verifies that validateAndFixToolResultIds rewrites wrong-idtool-1. To make the boundary between the two user-message branches fully explicit, you could additionally assert that the block is still a tool_result (i.e., not converted to a text "Tool result:\n…" block). The current toEqual does this implicitly, but a short comment or extra expect(result.content[0].type).toBe("tool_result") would document intent and guard against future regressions where the branch order changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/task/__tests__/apiConversationHistory.spec.ts` around lines 103 -
121, Add an explicit assertion that the user block remains a tool_result after
validation to document and guard the branch boundary in
prepareApiConversationMessage; after calling prepareApiConversationMessage (used
to exercise validateAndFixToolResultIds) assert result.content[0].type ===
"tool_result" (or equivalently expect(...).not.toBe("text")) so the test ensures
the block was corrected but not converted into a text "Tool result" block.
src/core/task/apiConversationHistory.ts (1)

58-62: 💤 Low value

Loss of type safety via any cast.

messageWithTs: any (and the any parameters in prependContentBlock/appendContentBlock) discards all Anthropic.MessageParam/ApiMessage type checking for the assistant flow. Returning ApiMessage from an any value also bypasses the declared return type. Consider typing this as ApiMessage & Record<string, unknown> (or a small union of permitted shapes) so the assignments to reasoning_details, id, and content blocks are checked.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/task/apiConversationHistory.ts` around lines 58 - 62, Replace the
loose any usage with a properly constrained type so TypeScript enforces expected
message shape: change messageWithTs’s type from any to something like ApiMessage
& Record<string, unknown> (or a small union of permitted shapes) and update the
signatures of prependContentBlock and appendContentBlock to accept
Anthropic.MessageParam | ApiMessage (or the same constrained type) instead of
any; ensure assignments to reasoning_details, id, and added content blocks are
compatible with the new type so the function returns an ApiMessage without
bypassing type checks (refer to messageWithTs, prependContentBlock,
appendContentBlock, reasoning_details, id, ApiMessage, and
Anthropic.MessageParam).
src/core/webview/PendingEditOperationStore.ts (1)

11-12: 💤 Low value

Consider consolidating identical type aliases.

PendingEditOperationInput and PendingEditOperationView are structurally identical. While they serve different semantic purposes (input to set vs output from get), using the same type alias for both would reduce duplication.

♻️ Consolidate type aliases
-export type PendingEditOperationInput = Omit<PendingEditOperation, "timeoutId" | "createdAt">
-export type PendingEditOperationView = Omit<PendingEditOperation, "timeoutId" | "createdAt">
+export type PendingEditOperationData = Omit<PendingEditOperation, "timeoutId" | "createdAt">

Then update the method signatures:

set(operationId: string, editData: PendingEditOperationData): void
get(operationId: string): PendingEditOperationData | undefined
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/webview/PendingEditOperationStore.ts` around lines 11 - 12, The two
identical type aliases PendingEditOperationInput and PendingEditOperationView
should be consolidated into a single alias (e.g., PendingEditOperationData) and
then update all uses: replace PendingEditOperationInput and
PendingEditOperationView with the new PendingEditOperationData, and adjust the
store method signatures so set(operationId: string, editData:
PendingEditOperationData): void and get(operationId: string):
PendingEditOperationData | undefined; update any references inside
PendingEditOperationStore (methods set and get and related callers) to use the
single consolidated alias.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/core/task/__tests__/apiConversationHistory.spec.ts`:
- Around line 103-121: Add an explicit assertion that the user block remains a
tool_result after validation to document and guard the branch boundary in
prepareApiConversationMessage; after calling prepareApiConversationMessage (used
to exercise validateAndFixToolResultIds) assert result.content[0].type ===
"tool_result" (or equivalently expect(...).not.toBe("text")) so the test ensures
the block was corrected but not converted into a text "Tool result" block.

In `@src/core/task/apiConversationHistory.ts`:
- Around line 58-62: Replace the loose any usage with a properly constrained
type so TypeScript enforces expected message shape: change messageWithTs’s type
from any to something like ApiMessage & Record<string, unknown> (or a small
union of permitted shapes) and update the signatures of prependContentBlock and
appendContentBlock to accept Anthropic.MessageParam | ApiMessage (or the same
constrained type) instead of any; ensure assignments to reasoning_details, id,
and added content blocks are compatible with the new type so the function
returns an ApiMessage without bypassing type checks (refer to messageWithTs,
prependContentBlock, appendContentBlock, reasoning_details, id, ApiMessage, and
Anthropic.MessageParam).

In `@src/core/webview/PendingEditOperationStore.ts`:
- Around line 11-12: The two identical type aliases PendingEditOperationInput
and PendingEditOperationView should be consolidated into a single alias (e.g.,
PendingEditOperationData) and then update all uses: replace
PendingEditOperationInput and PendingEditOperationView with the new
PendingEditOperationData, and adjust the store method signatures so
set(operationId: string, editData: PendingEditOperationData): void and
get(operationId: string): PendingEditOperationData | undefined; update any
references inside PendingEditOperationStore (methods set and get and related
callers) to use the single consolidated alias.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 76891c15-78df-40bd-80cf-8c6741dcfb24

📥 Commits

Reviewing files that changed from the base of the PR and between 5a5b22e and d9efeec.

📒 Files selected for processing (6)
  • src/core/task/Task.ts
  • src/core/task/__tests__/apiConversationHistory.spec.ts
  • src/core/task/apiConversationHistory.ts
  • src/core/webview/ClineProvider.ts
  • src/core/webview/PendingEditOperationStore.ts
  • src/core/webview/__tests__/PendingEditOperationStore.spec.ts

@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

❌ Patch coverage is 91.84783% with 15 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/core/task/apiConversationHistory.ts 90.09% 11 Missing ⚠️
src/core/webview/ClineProvider.ts 83.33% 2 Missing ⚠️
src/core/webview/PendingEditOperationStore.ts 96.07% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

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