Skip to content

Conversation

@Scra3
Copy link
Member

@Scra3 Scra3 commented Jan 23, 2026

Summary

  • Add Anthropic provider support to @forestadmin/ai-proxy using @langchain/anthropic
  • Support all Claude models with tool calling capabilities
  • Maintain OpenAI-compatible response format for seamless integration
  • Unified configuration interface: both providers use same base fields (name, provider, model, apiKey)

Changes

  • Added @langchain/anthropic dependency
  • Added AnthropicConfiguration type with all Anthropic-specific options
  • Added ANTHROPIC_MODELS constant with supported Claude models
  • Implemented message conversion (OpenAI ↔ LangChain)
  • Implemented response conversion (LangChain → OpenAI format)
  • Added AnthropicUnprocessableError for error handling
  • Added comprehensive tests (38 new tests)

Test plan

  • All 86 tests pass
  • Build succeeds
  • Lint passes (only warnings for non-null assertions)

🤖 Generated with Claude Code

Add support for Anthropic's Claude models in the ai-proxy package using
@langchain/anthropic. This allows users to configure Claude as their AI
provider alongside OpenAI.

Changes:
- Add @langchain/anthropic dependency
- Add ANTHROPIC_MODELS constant with supported Claude models
- Add AnthropicConfiguration type and AnthropicModel type
- Add AnthropicUnprocessableError for Anthropic-specific errors
- Implement message conversion from OpenAI format to LangChain format
- Implement response conversion from LangChain format back to OpenAI format
- Add tool binding support for Anthropic with tool_choice conversion
- Add comprehensive tests for Anthropic provider

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@linear
Copy link

linear bot commented Jan 23, 2026

@qltysh
Copy link

qltysh bot commented Jan 23, 2026

1 new issue

Tool Category Rule Count
qlty Structure Function with many returns (count = 6): convertToolChoiceToLangChain 1

@qltysh
Copy link

qltysh bot commented Jan 23, 2026

Qlty

Coverage Impact

This PR will not change total coverage.

🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

tool_calls: msg.tool_calls.map(tc => ({
id: tc.id,
name: tc.function.name,
args: JSON.parse(tc.function.arguments),
Copy link
Member Author

Choose a reason for hiding this comment

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

JSON.parse() can throw if tc.function.arguments contains malformed JSON. This call is outside the try-catch block (line 210), so errors would propagate as unhandled SyntaxError instead of being wrapped in AnthropicUnprocessableError.

OpenAI API can return malformed JSON in edge cases (documented issues).

Fix packages/ai-proxy/src/provider-dispatcher.ts:259: Wrap JSON.parse in try-catch or move convertMessagesToLangChain call inside the existing try-catch block at line 210

});
}

return new AIMessage(msg.content);
Copy link
Member Author

Choose a reason for hiding this comment

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

LangChain message constructors (SystemMessage, HumanMessage, AIMessage) fail with null content. OpenAI API allows content: null for assistant messages (API spec).

The OpenAIMessage interface at line 117 defines content: string, but should allow null. Line 255 handles this correctly with msg.content || '', but lines 249, 251, 264, 267, 271 pass content directly.

Suggested change
return new AIMessage(msg.content);
return new AIMessage(msg.content || '\);

… dispatcher

- Move convertMessagesToLangChain inside try-catch to properly handle JSON.parse errors
- Update OpenAIMessage interface to allow null content (per OpenAI API spec)
- Add null content handling for all message types with fallback to empty string

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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