Skip to content

feat: support content + toolCalls together in fixture responses#92

Merged
jpr5 merged 4 commits intomainfrom
worktree-immutable-baking-graham
Apr 8, 2026
Merged

feat: support content + toolCalls together in fixture responses#92
jpr5 merged 4 commits intomainfrom
worktree-immutable-baking-graham

Conversation

@AlemTuzlak
Copy link
Copy Markdown
Contributor

Summary

  • Adds ContentWithToolCallsResponse type to FixtureResponse union, allowing fixtures to specify both content and toolCalls in a single response
  • Implements combined streaming and non-streaming support across all 4 provider formats: OpenAI Chat Completions, OpenAI Responses API, Anthropic Messages, and Gemini
  • Updates stream-collapse functions to preserve both content and toolCalls when recording responses that contain both
  • Content is streamed first, then tool calls, with the appropriate tool-call finish reason per provider (tool_calls, tool_use, FUNCTION_CALL)

Test plan

  • 17 new tests covering streaming + non-streaming for all 4 providers, plus stream-collapse coexistence for OpenAI/Anthropic/Gemini/Ollama
  • Full suite: 2043 tests pass, 0 failures
  • Lint and format clean

Copy link
Copy Markdown
Contributor

@jpr5 jpr5 left a comment

Choose a reason for hiding this comment

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

PR Review Summary

Reviewed by 3 specialized agents (code-reviewer, silent-failure + type-design, test-reviewer) across all 9 changed source files.


Zero code bugs found. Implementation is correct across all 4 providers.

The ContentWithToolCallsResponse type, routing, streaming, non-streaming, and stream-collapse changes are all well-implemented. Content streams first, then tool calls, with correct finish reasons per provider (tool_calls, tool_use, FUNCTION_CALL). Handler ordering is correct everywhere — isContentWithToolCallsResponse checked before isTextResponse/isToolCallResponse. 17 tests cover type guards, all 4 providers (streaming + non-streaming), and collapse coexistence.


Must fix (1)

1. Internal planning docs committed to repo

Files: docs/superpowers/plans/2026-04-08-content-with-toolcalls.md, docs/superpowers/specs/2026-04-08-content-with-toolcalls-design.md

These are internal development artifacts (2,105 lines) and should not be committed to the public repository. Remove before merge.


Needs rebase

The branch is ~20 commits behind main (merge base 7aac519). It will conflict with:

  • PR #81 (reasoning support across all providers)
  • PR #88 (reasoning_content for OpenRouter)
  • PR #89 (action.query for web_search_call)
  • PR #90 (docs link cleanup)

Rebase before merge.


Informational (no action required, but worth noting)

Type guard overlap

isTextResponse and isToolCallResponse both return true for combined responses (the test at line 30-38 documents this). Current handler ordering prevents bugs, but any future code that checks isTextResponse first without the combined guard would silently drop toolCalls.

Providers not updated

Bedrock, Bedrock Converse, Ollama, Cohere, and WebSocket handlers don't check for isContentWithToolCallsResponse. A combined fixture routed through them silently drops toolCalls (falls through to isTextResponse). Acceptable scope limitation for this PR.

Collapse inconsistency

collapseCohereSSE and collapseBedrockEventStream were NOT updated to preserve content alongside toolCalls, unlike the other 4 collapse functions. Minor inconsistency.

Test weakness

The Responses API streaming test (line 170-181) only asserts textDelta is defined, not the actual value. Every other provider's streaming test verifies exact content strings.

Dead field

ContentWithToolCallsResponse.finishReason is declared but never read — all handlers hardcode the finish reason.

🤖 Reviewed with Claude Code

@jpr5 jpr5 force-pushed the worktree-immutable-baking-graham branch from 6c9534d to 8c14ddd Compare April 8, 2026 22:31
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 8, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@copilotkit/aimock@92

commit: 6a17828

jpr5
jpr5 previously approved these changes Apr 8, 2026
Copy link
Copy Markdown
Contributor

@jpr5 jpr5 left a comment

Choose a reason for hiding this comment

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

Both findings from Round 1 addressed:

  1. Internal docs removed (2,105 lines) — ✓
  2. Responses API streaming test strengthened with actual content assertion — ✓

Branch rebased on current main. Implementation is correct across all 4 providers. LGTM.

🤖 Reviewed with Claude Code

New FixtureResponse variant for fixtures that specify both content and
toolCalls. Includes isContentWithToolCallsResponse guard, streaming
builder (buildContentWithToolCallsChunks), and non-streaming builder
(buildContentWithToolCallsCompletion) for OpenAI Chat Completions.
Streaming and non-streaming support for ContentWithToolCallsResponse in
OpenAI Chat Completions (server.ts), OpenAI Responses API (responses.ts),
Anthropic Messages (messages.ts), and Gemini (gemini.ts). Content streams
first, then tool calls, with correct finish reasons per provider
(tool_calls, tool_use, FUNCTION_CALL). Includes shared helper extraction
in responses.ts and parseToolCallPart refactor in gemini.ts.
When a recorded stream contains both content and tool calls, collapse
functions now return both fields instead of dropping content. Updated
collapseOpenAISSE, collapseAnthropicSSE, collapseGeminiSSE, and
collapseOllamaNDJSON for record-and-replay fidelity.
Type guard tests (5), streaming + non-streaming per provider (8),
stream-collapse coexistence tests for OpenAI/Anthropic/Gemini/Ollama (4).
@jpr5 jpr5 force-pushed the worktree-immutable-baking-graham branch from ca08f8a to 6a17828 Compare April 8, 2026 22:39
@jpr5 jpr5 merged commit 307073b into main Apr 8, 2026
18 checks passed
@jpr5 jpr5 deleted the worktree-immutable-baking-graham branch April 8, 2026 22:41
jpr5 added a commit that referenced this pull request Apr 8, 2026
## Summary

- **Per-test sequence isolation** via `X-Test-Id` header — each test
gets its own fixture match counters across all 12 HTTP + 3 WebSocket
handlers (#93)
- **Combined content + toolCalls** in fixture responses — new
`ContentWithToolCallsResponse` type across OpenAI Chat, Responses,
Anthropic Messages, and Gemini with stream collapse support (#92)
- **OpenRouter reasoning_content** support (#88)
- **Clean URLs** for docs site — all pages restructured as directories,
.html extensions removed from links
- Fix `web_search_call` items to use `action.query` matching real OpenAI
API (#89)
- Bump aimock-pytest to 0.3.0

## Version bumps
- `package.json`: 1.8.0 → 1.9.0
- `pyproject.toml`: 0.2.0 → 0.3.0
- `Chart.yaml` appVersion: 1.8.0 → 1.9.0
- `plugin.json` / `marketplace.json`: 1.8.0 → 1.9.0

## Test plan
- [x] All 2206 tests pass (including 80 new clean-URL validation tests)
- [x] Build passes
- [x] Prettier clean
- [ ] npm publish triggers automatically on merge via OIDC workflow
- [ ] Verify v1.9.0 appears on npm after merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

2 participants