Skip to content

feat(server): add Anthropic Messages API ingress endpoint#343

Merged
SantiagoDePolonia merged 4 commits into
mainfrom
feat/anthropic-messages-ingress
May 21, 2026
Merged

feat(server): add Anthropic Messages API ingress endpoint#343
SantiagoDePolonia merged 4 commits into
mainfrom
feat/anthropic-messages-ingress

Conversation

@SantiagoDePolonia
Copy link
Copy Markdown
Contributor

@SantiagoDePolonia SantiagoDePolonia commented May 21, 2026

Summary

Adds a managed POST /v1/messages endpoint (plus POST /v1/messages/count_tokens) that accepts the Anthropic Messages API request dialect and routes it to any configured provider — not just Anthropic.

The Anthropic request is translated once at the ingress boundary into the canonical core.ChatRequest, then runs through the unchanged chat-completions pipeline. Model aliases, workflow policy, budgets, failover, the response cache, usage/cost tracking, and audit logging all apply — with zero changes to gateway, providers, usage, or auditlog.

This mirrors the existing /v1/responses ingress dialect. See ADR-0007 for the full rationale and tradeoffs.

User-visible impact

  • Clients and SDKs that speak the Anthropic Messages format can point at GoModel unchanged.
  • Anthropic-format requests can be routed to OpenAI, Gemini, Bedrock, Groq, and any other configured provider.
  • Responses use the Anthropic Messages shape (type: "message", content blocks, stop_reason, usage); errors use the Anthropic error envelope ({"type":"error","error":{...}}).
  • Streaming emits the Anthropic SSE sequence (message_start / content_block_* / message_delta / message_stop).
  • The OpenAI-compatible API is unchanged — /v1/chat/completions still returns the OpenAI shape.

What's included

  • New isolated internal/anthropicapi package: wire DTOs, request/response translation, OpenAI→Anthropic SSE stream conversion, error-envelope mapping.
  • Thin HTTP glue in internal/server/messages_handler.go; routes registered in http.go, classified in core/endpoints.go (dialect anthropic).
  • count_tokens returns a provider-agnostic heuristic input-token estimate.
  • handleError is now dialect-aware (writeGatewayError) so middleware errors (auth, workflow resolution) also render the Anthropic envelope.

Provider-specific behavior

  • Maps OpenAI stop → Anthropic stop_sequences in the anthropic provider request translation. This also fixes a pre-existing gap where stop was dropped for /v1/chat/completions routed to Anthropic.
  • A /v1/messages request routed to the Anthropic provider is lossy (cache_control, thinking signatures, server tools do not survive the canonical hop) — clients needing byte-exact fidelity should use the /p/anthropic/v1/messages passthrough.

Bugs found during live testing (and fixed)

Tested extensively with curl against real provider keys (Anthropic, OpenAI, Groq, Gemini): non-streaming, streaming, function calling (incl. multi-turn tool_result), multimodal images, extended thinking, count_tokens, error cases, response cache, cost tracking, audit logs.

  1. Middleware errors rendered the OpenAI envelope on /v1/messages — auth/bad-model errors bypass the handler. Fixed via dialect-aware handleError; let us delete the duplicate error helpers.
  2. stop_sequences silently dropped when routed to the Anthropic provider — the provider never read stop. Fixed (see above).
  3. Unsupported content blocks (document/PDF) silently dropped — the model answered as if no attachment was sent. Now returns a clear 400.
  4. Streaming converter never closed the underlying streamRead() set closed=true on EOF, so Close() skipped body.Close() → no audit log, no usage/cost record, leaked provider connection. Fixed so Close always propagates.

Testing

  • go build ./... ✓ · full go test ./... ✓ · golangci-lint 0 issues · gofmt clean · make test-race ✓ (pre-commit).
  • Regression tests added: stream-close propagation, dialect-aware error rendering, unsupported-block rejection, thinking-block drop, stop_sequences mapping.
  • Verified via direct DB inspection: streaming /v1/messages records usage rows (with cost) and stream=1 audit rows; cache hits recorded at 0.000000 with cache_type=exact.

Docs

  • New ADR-0007 and a docs page (docs/advanced/anthropic-messages-api.mdx) with nav entry.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Anthropic Messages API endpoints: POST /v1/messages (Anthropic-shaped requests routed into the platform chat pipeline) and POST /v1/messages/count_tokens (provider-agnostic token estimate).
    • Anthropic-style SSE streaming output and dialect-specific error envelopes.
  • Documentation

    • Added ADR and advanced guide detailing behavior, streaming event sequence, cost/audit attribution, known limitations, and a byte-exact passthrough option.

Review Change Stack

Add a managed POST /v1/messages endpoint (plus /v1/messages/count_tokens)
that accepts the Anthropic Messages API request dialect and routes it to
any configured provider through the unchanged chat-completions pipeline.

The Anthropic request is translated once at the ingress boundary into the
canonical core.ChatRequest, so model aliases, workflow policy, budgets,
failover, the response cache, usage/cost tracking, and audit logging all
apply with no changes to gateway, providers, usage, or auditlog.

- New isolated internal/anthropicapi package: wire DTOs, request/response
  translation, OpenAI->Anthropic SSE stream conversion, error envelope.
- Anthropic-format SSE streaming with the message_start / content_block_* /
  message_delta / message_stop event sequence.
- count_tokens returns a provider-agnostic heuristic input-token estimate.
- Errors render in the Anthropic error envelope end to end; handleError is
  now dialect-aware (writeGatewayError), used by the auth middleware too.
- Map OpenAI stop -> Anthropic stop_sequences in the anthropic provider
  request translation (also fixes stop for /v1/chat/completions).
- Reject document/unknown content blocks with a clear 400 instead of
  silently dropping them.

See ADR-0007 for the design rationale and tradeoffs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR adds a managed Anthropic Messages API ingress path. It changes:

  • Adds /v1/messages and /v1/messages/count_tokens handlers.
  • Translates Anthropic Messages requests into the existing canonical chat pipeline.
  • Converts chat responses and streaming SSE back into Anthropic response shapes.
  • Adds dialect-aware Anthropic error envelopes for request and middleware failures.
  • Documents the new endpoint, tradeoffs, and passthrough limitations.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the latest changed code.
  • The trailing-body validation now rejects extra JSON values and malformed suffixes.
  • The latest test changes strengthen coverage without changing runtime behavior.

Reviews (3): Last reviewed commit: "fix(server): fully reject trailing bytes..." | Re-trigger Greptile

Comment thread internal/anthropicapi/request.go
Comment thread internal/anthropicapi/request.go Outdated
Comment thread internal/anthropicapi/request.go Outdated
Comment thread internal/anthropicapi/request.go Outdated
Comment thread internal/anthropicapi/request.go
Comment thread internal/anthropicapi/request.go Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

Adds managed Anthropic /v1/messages ingress: Anthropic wire types and translation to canonical chat requests, response/SSE conversion back to Anthropic shapes, server endpoints (/v1/messages, /v1/messages/count_tokens), dialect-aware error rendering, provider stop-sequence mapping, and docs/tests.

Changes

Anthropic Messages API Implementation

Layer / File(s) Summary
Anthropic wire types and request translation
internal/anthropicapi/types.go, internal/anthropicapi/request.go, internal/anthropicapi/request_test.go
Adds Anthropic wire DTOs, DecodeMessagesRequest, ToChatRequest, tool/role/content conversions, EstimateInputTokens, and tests for decoding, validation, content block handling, tools, thinking/reasoning mapping, and extra-field passthrough.
Response translation and SSE conversion
internal/anthropicapi/response.go, internal/anthropicapi/response_test.go, internal/anthropicapi/stream.go, internal/anthropicapi/stream_test.go
Implements FromChatResponse to emit Anthropic MessagesResponse (IDs, usage, content blocks, stop reasons) and NewStreamConverter to convert OpenAI-style SSE into Anthropic SSE events; tests cover streaming text, tool calls, usage, closure, and empty streams.
Error envelope mapping
internal/anthropicapi/errors.go, internal/anthropicapi/errors_test.go
Introduces ErrorFromGateway to map *core.GatewayError → (HTTP status, Anthropic ErrorResponse) with error-type mapping and nil-error handling; unit tests added.
Server routing and message handlers
internal/core/endpoints.go, internal/server/http.go, internal/server/messages_handler.go, internal/server/messages_handler_test.go
Registers /v1/messages and /v1/messages/count_tokens, implements handlers that decode Anthropic requests, dispatch via translated inference path (streaming/non-streaming), wrap streams with the converter, provide heuristic token counting, and add tests for non-streaming, streaming, invalid requests, and token counting.
Dialect-aware error handling & auth
internal/server/error_support.go, internal/server/error_support_test.go, internal/server/auth.go
Refactors handleError to normalize errors, adds writeGatewayError which uses anthropicapi.ErrorFromGateway for Anthropic-dialect paths, adds requestDialect helper, and updates auth middleware to use centralized error responses; tests validate envelope differences.
Streaming infrastructure and provider updates
internal/server/translated_inference_service.go, internal/providers/anthropic/types.go, internal/providers/anthropic/request_translation.go, internal/providers/anthropic/anthropic_test.go
Extends handleStreamingReadCloser with optional outerWrap wrapper (call sites pass nil), adds StopSequences mapping from ExtraFields["stop"] (string/array handling) in Anthropic provider request translation, and tests stop-sequence mapping.
Architecture documentation and nav
docs/adr/0007-anthropic-messages-ingress.md, docs/advanced/anthropic-messages-api.mdx, docs/docs.json
Adds ADR describing design, limitations and alternatives; user docs for /v1/messages and /v1/messages/count_tokens including SSE/event formats and limitations; updates docs navigation.

Sequence Diagram

sequenceDiagram
  participant Client
  participant Server as /v1/messages Handler
  participant RequestTranslator as anthropicapi.ToChatRequest
  participant Dispatcher as dispatchMessages
  participant Provider
  participant ResponseTranslator as anthropicapi.FromChatResponse
  participant StreamConverter as anthropicapi.NewStreamConverter

  Client->>Server: POST /v1/messages (Anthropic dialect)
  Server->>RequestTranslator: MessagesRequest body
  RequestTranslator->>RequestTranslator: validate + normalize roles
  RequestTranslator->>RequestTranslator: convert tools/messages/reasoning
  RequestTranslator->>Dispatcher: core.ChatRequest
  Dispatcher->>Dispatcher: enforce budget constraints
  alt streaming mode
    Dispatcher->>Provider: StreamChatCompletion
    Provider->>Dispatcher: OpenAI SSE stream
    Dispatcher->>StreamConverter: wrap stream
    StreamConverter->>StreamConverter: parse chunks, emit Anthropic SSE
    StreamConverter->>Client: Anthropic SSE events
  else non-streaming mode
    Dispatcher->>Provider: ExecuteChatCompletion
    Provider->>Dispatcher: core.ChatResponse
    Dispatcher->>ResponseTranslator: ChatResponse
    ResponseTranslator->>Client: MessagesResponse JSON
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

release:internal

Poem

🐰 I hopped through bytes and event streams wide,
I translated messages with careful stride,
I turned chunks to SSE and IDs to msg_,
I counted tokens by character scuff,
Now Anthropic talks, and the rabbits cheer!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.03% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the primary change: adding a new Anthropic Messages API ingress endpoint at POST /v1/messages with supporting infrastructure.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/anthropic-messages-ingress

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.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 21, 2026

Two issues found while reviewing the Anthropic Messages ingress:

- top_k was carried through ChatRequest.ExtraFields, which MarshalJSON
  merges into the wire body. The OpenAI-family providers forward request
  fields verbatim and reject unknown ones, so an Anthropic request with
  the legitimate top_k field hard-failed with a 400 when routed to
  OpenAI, Groq, xAI, DeepSeek, or OpenRouter. Drop top_k (it has no
  portable OpenAI-compatible equivalent); top_p and temperature are kept.

- Anthropic server/built-in tools (web search, code execution, …) carry
  a versioned tool type. The Tool DTO had no Type field, so a server
  tool decoded as a custom tool and was mistranslated into a phantom
  custom function the gateway cannot execute. Add Tool.Type and reject
  server tools with a clear 400, consistent with how unsupported content
  blocks are handled.

Update ADR-0007 and the docs page accordingly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mintlify
Copy link
Copy Markdown

mintlify Bot commented May 21, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
gomodel 🟢 Ready View Preview May 21, 2026, 1:46 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 2

🤖 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.

Inline comments:
In `@docs/adr/0007-anthropic-messages-ingress.md`:
- Around line 83-88: Add a language tag to the fenced code block that begins
with the lines "provider chat SSE" / "→ ObservedSSEStream(...)" so markdownlint
MD040 is satisfied; update the opening fence from ``` to ```text (or another
appropriate language) so the block is annotated (the block containing provider
chat SSE → ObservedSSEStream → anthropicapi.StreamConverter → HTTP response).

In `@internal/anthropicapi/errors_test.go`:
- Around line 17-53: Add two table-driven test cases to the existing test slice
used by TestErrorFromGateway in internal/anthropicapi/errors_test.go to cover
the special anthropicErrorType branches: one for request-too-large using
core.NewInvalidRequestErrorWithStatus(http.StatusRequestEntityTooLarge, "payload
too large", nil) with wantType "request_too_large" and wantStatus
http.StatusRequestEntityTooLarge, and one for forbidden using
core.ParseProviderError("p", http.StatusForbidden, []byte("forbidden"), nil)
with wantType "permission_error" and wantStatus http.StatusForbidden so the
anthropicErrorType mapping for 413 and 403 is exercised.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9f811ed6-e6c7-4a4b-83d4-9339f1f0f740

📥 Commits

Reviewing files that changed from the base of the PR and between c9a4271 and 8e45b84.

📒 Files selected for processing (23)
  • docs/adr/0007-anthropic-messages-ingress.md
  • docs/advanced/anthropic-messages-api.mdx
  • docs/docs.json
  • internal/anthropicapi/errors.go
  • internal/anthropicapi/errors_test.go
  • internal/anthropicapi/request.go
  • internal/anthropicapi/request_test.go
  • internal/anthropicapi/response.go
  • internal/anthropicapi/response_test.go
  • internal/anthropicapi/stream.go
  • internal/anthropicapi/stream_test.go
  • internal/anthropicapi/types.go
  • internal/core/endpoints.go
  • internal/providers/anthropic/anthropic_test.go
  • internal/providers/anthropic/request_translation.go
  • internal/providers/anthropic/types.go
  • internal/server/auth.go
  • internal/server/error_support.go
  • internal/server/error_support_test.go
  • internal/server/http.go
  • internal/server/messages_handler.go
  • internal/server/messages_handler_test.go
  • internal/server/translated_inference_service.go

Comment thread docs/adr/0007-anthropic-messages-ingress.md Outdated
Comment thread internal/anthropicapi/errors_test.go
Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@internal/anthropicapi/request.go`:
- Around line 306-312: The validation error uses the shorthand path
"/p/anthropic" which is misleading; update the error text created in the tool
type check (the block referencing tool.Type and returning
core.NewInvalidRequestError) to point users to the full passthrough endpoint
"/p/anthropic/v1/messages" instead of "/p/anthropic" so the message reads
something like "... use the /p/anthropic/v1/messages passthrough for
provider-native tools".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 55180a33-2236-4a27-b214-7eae41fd87b1

📥 Commits

Reviewing files that changed from the base of the PR and between 8e45b84 and 62aa015.

📒 Files selected for processing (5)
  • docs/adr/0007-anthropic-messages-ingress.md
  • docs/advanced/anthropic-messages-api.mdx
  • internal/anthropicapi/request.go
  • internal/anthropicapi/request_test.go
  • internal/anthropicapi/types.go

Comment thread internal/anthropicapi/request.go
Address PR review feedback on the Messages ingress dialect:

- Reject messages whose role is not "user" or "assistant" instead of
  silently coercing every unknown role (e.g. a typo) to "user", which
  changed conversation semantics for malformed requests.
- Reject a present-but-malformed `system` value (wrong shape or a
  non-text block) instead of silently dropping it, which made the model
  run without the caller's instructions.
- Reject malformed or non-text `tool_result` content instead of
  silently converting it to an empty string, which made the downstream
  provider answer as if the tool returned no data.
- Reject request bodies with trailing bytes after the JSON object so a
  malformed body cannot look valid while audit/cache inputs disagree.
- Point validation error messages at the full passthrough path
  `/p/anthropic/v1/messages` rather than the `/p/anthropic` shorthand.
- Add a language tag to the ADR fenced code block (markdownlint MD040).
- Cover the request_too_large (413) and permission_error (403) branches
  of anthropicErrorType in TestErrorFromGateway.

Tool-result blocks are still emitted before the user text of the same
message: that ordering is required by the OpenAI message contract (tool
messages must immediately follow the assistant tool-call message), so
the existing order is correct and left unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@internal/anthropicapi/request_test.go`:
- Around line 64-87: The test TestToChatRequestRejectsInvalidShapes currently
only checks that ToChatRequest returns a *core.GatewayError but does not assert
the specific error type; update the test to also assert that the returned
gatewayErr.Type equals core.ErrorTypeInvalidRequest (similar to
TestToChatRequestRejectsServerTool and
TestToChatRequestRejectsUnsupportedContentBlock) so the Anthropic error-envelope
mapping remains validated. Locate the test function
TestToChatRequestRejectsInvalidShapes and after verifying err is a
*core.GatewayError, cast it to gatewayErr and add an assertion that
gatewayErr.Type == core.ErrorTypeInvalidRequest, failing the test if it differs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: be31b772-b2d1-4a3d-903b-92e83906b59a

📥 Commits

Reviewing files that changed from the base of the PR and between 62aa015 and 4485ded.

📒 Files selected for processing (4)
  • docs/adr/0007-anthropic-messages-ingress.md
  • internal/anthropicapi/errors_test.go
  • internal/anthropicapi/request.go
  • internal/anthropicapi/request_test.go

Comment thread internal/anthropicapi/request_test.go
Comment thread internal/anthropicapi/request.go Outdated
Comment thread internal/anthropicapi/request.go
Address follow-up PR review feedback:

- DecodeMessagesRequest now requires a second decode to reach io.EOF
  instead of relying on json.Decoder.More(). More() returns false for a
  trailing "]" or "}", so those bytes slipped through; decoding one more
  value and requiring EOF rejects every trailing-byte case.
- Tighten TestToChatRequestRejectsInvalidShapes to assert the error type
  is core.ErrorTypeInvalidRequest, matching the sibling rejection tests
  so the Anthropic error-envelope mapping stays validated.

The "require tool_result content" suggestion is intentionally not
applied: Anthropic's Messages API treats tool_result `content` as
optional (only `tool_use_id` and `type` are required), so rejecting an
omitted or empty value would make GoModel stricter than the API it
emulates and break requests that work directly against Anthropic. An
empty tool result faithfully represents a tool that produced no output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
internal/anthropicapi/request_test.go (1)

58-60: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Tighten TestToChatRequestValidation to assert core.ErrorTypeInvalidRequest.

This sibling test still only checks for *core.GatewayError, while TestToChatRequestRejectsInvalidShapes (lines 83-86), TestToChatRequestRejectsServerTool (lines 221-224), and TestToChatRequestRejectsUnsupportedContentBlock (lines 332-335) all verify Type == core.ErrorTypeInvalidRequest. The Anthropic error-envelope mapping keys off Type, so a future regression that surfaces these as a non-invalid type would slip past this assertion.

♻️ Proposed change
-			if _, ok := err.(*core.GatewayError); !ok {
-				t.Fatalf("expected *core.GatewayError, got %T", err)
+			gatewayErr, ok := err.(*core.GatewayError)
+			if !ok || gatewayErr.Type != core.ErrorTypeInvalidRequest {
+				t.Fatalf("expected invalid_request_error, got %T: %v", err, err)
 			}
🤖 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 `@internal/anthropicapi/request_test.go` around lines 58 - 60, The test
TestToChatRequestValidation currently only asserts the error is a
*core.GatewayError; update the assertion to also check that the error's Type
equals core.ErrorTypeInvalidRequest. Locate where the test does the type check
(the err.(*core.GatewayError) branch) and add an assertion that the
mappedGatewayErr.Type == core.ErrorTypeInvalidRequest (or equivalent) so the
test fails if the error envelope type is not ErrorTypeInvalidRequest.
🤖 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.

Duplicate comments:
In `@internal/anthropicapi/request_test.go`:
- Around line 58-60: The test TestToChatRequestValidation currently only asserts
the error is a *core.GatewayError; update the assertion to also check that the
error's Type equals core.ErrorTypeInvalidRequest. Locate where the test does the
type check (the err.(*core.GatewayError) branch) and add an assertion that the
mappedGatewayErr.Type == core.ErrorTypeInvalidRequest (or equivalent) so the
test fails if the error envelope type is not ErrorTypeInvalidRequest.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 94fefead-5985-46b5-83bc-5021d3d21fae

📥 Commits

Reviewing files that changed from the base of the PR and between 4485ded and d99f013.

📒 Files selected for processing (2)
  • internal/anthropicapi/request.go
  • internal/anthropicapi/request_test.go

@SantiagoDePolonia SantiagoDePolonia merged commit 32cda0e into main May 21, 2026
19 checks passed
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