Skip to content

feat: add ChatOrcaRouter chat model node#6447

Open
zhenjunchen-png wants to merge 2 commits into
FlowiseAI:mainfrom
zhenjunchen-png:feature/orcarouter-chat-model
Open

feat: add ChatOrcaRouter chat model node#6447
zhenjunchen-png wants to merge 2 commits into
FlowiseAI:mainfrom
zhenjunchen-png:feature/orcarouter-chat-model

Conversation

@zhenjunchen-png
Copy link
Copy Markdown

@zhenjunchen-png zhenjunchen-png commented May 29, 2026

Summary

Adds a new ChatOrcaRouter chat model node, following the same pattern used for ChatOpenRouter (#3865) and ChatCometAPI (#5160). OrcaRouter is an OpenAI-compatible LLM router that exposes 150+ models from OpenAI, Anthropic, Google, DeepSeek, xAI, MiniMax, Qwen and others behind a single endpoint, plus an orcarouter/auto router that picks the best upstream per request.

Disclosure: I'm an engineer on the OrcaRouter team.

What changed

  • New credential: packages/components/credentials/OrcaRouterApi.credential.ts, a single password field for the OrcaRouter API key (keys begin with sk-orca-).
  • New node: packages/components/nodes/chatmodels/ChatOrcaRouter/, containing ChatOrcaRouter.ts (INode implementation), FlowiseChatOrcaRouter.ts (LangChain ChatOpenAI subclass implementing IVisionChatModal), orcaRouter.svg (icon), and ChatOrcaRouter.test.ts (co-located jest tests covering the model list, credential wiring, default and custom base URL, attribution headers, blank-temperature behaviour, and Base Options JSON parsing).
  • Streaming list: added chatOrcaRouter to streamAvailableLLMs['Chat Models'] in packages/server/src/utils/index.ts, matching the change made for chatCometAPI.

The node wraps @langchain/openai's ChatOpenAI with configuration.baseURL = 'https://api.orcarouter.ai/v1', exposes the usual chat-model parameters (temperature, max tokens, top P, frequency/presence penalty, timeout, streaming, image uploads), and injects HTTP-Referer: https://www.orcarouter.ai/ and X-Title: Flowise attribution headers by default (overridable through the existing Base Options JSON field, same shape as the OpenRouter node).

The Model Name field is an asyncOptions dropdown with freeSolo: true. Its listModels loader fetches OrcaRouter's public model catalog and filters it to chat-completions models, led by orcarouter/auto, so new models appear without a code change. If the fetch fails it falls back to a small set of flagship presets, and users can always type any free-form model id.

Companion docs PR

FlowiseAI/FlowiseDocs: FlowiseAI/FlowiseDocs#216

Testing

  • pnpm --filter flowise-components test: new co-located jest suite passes (ChatOrcaRouter.test.ts).
  • pnpm lint and pnpm build clean.
  • Validated against the live OrcaRouter API with a real sk-orca- key: non-stream chat, stream chat, tool calling, 401 on a bad key, and 4xx on an invalid model all behave as expected.
  • Local UI run (pnpm start): dragged the new ChatOrcaRouter node onto a chatflow, wired it to an LLM Chain, sent messages with both orcarouter/auto and pinned models, confirmed responses and attribution headers in the OrcaRouter console.

Add an OrcaRouter chat model node (an OpenAI-compatible LLM router) following
the ChatOpenRouter / ChatCometAPI pattern: a credential, the node plus a vision
subclass, an icon, and co-located tests. The Model Name dropdown is loaded from
the OrcaRouter catalog and is freeSolo. Also register chatOrcaRouter in the
server streaming list.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the ChatOrcaRouter integration, which connects to OrcaRouter, an OpenAI-compatible LLM router. It includes credential configuration, the chat model node implementation, tests, and registration for streaming. The feedback suggests replacing simple truthy checks for numeric parameters (like temperature and penalties) with explicit nullish and empty-string checks to prevent valid values of 0 from being ignored.

Comment on lines +227 to +232
if (temperature) obj.temperature = parseFloat(temperature)
if (maxTokens) obj.maxTokens = parseInt(maxTokens, 10)
if (topP) obj.topP = parseFloat(topP)
if (frequencyPenalty) obj.frequencyPenalty = parseFloat(frequencyPenalty)
if (presencePenalty) obj.presencePenalty = parseFloat(presencePenalty)
if (timeout) obj.timeout = parseInt(timeout, 10)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using simple truthy checks (if (temperature)) can lead to bugs when valid values like 0 (for temperature, penalties, or topP) are passed. If these values are resolved as numbers (e.g., from variables or overrides), 0 evaluates to false and the setting is incorrectly ignored. It is safer to explicitly check against null or undefined using loose equality (!= null), and empty strings.

Suggested change
if (temperature) obj.temperature = parseFloat(temperature)
if (maxTokens) obj.maxTokens = parseInt(maxTokens, 10)
if (topP) obj.topP = parseFloat(topP)
if (frequencyPenalty) obj.frequencyPenalty = parseFloat(frequencyPenalty)
if (presencePenalty) obj.presencePenalty = parseFloat(presencePenalty)
if (timeout) obj.timeout = parseInt(timeout, 10)
if (temperature != null && temperature !== '') obj.temperature = parseFloat(temperature)
if (maxTokens != null && maxTokens !== '') obj.maxTokens = parseInt(maxTokens, 10)
if (topP != null && topP !== '') obj.topP = parseFloat(topP)
if (frequencyPenalty != null && frequencyPenalty !== '') obj.frequencyPenalty = parseFloat(frequencyPenalty)
if (presencePenalty != null && presencePenalty !== '') obj.presencePenalty = parseFloat(presencePenalty)
if (timeout != null && timeout !== '') obj.timeout = parseInt(timeout, 10)
References
  1. In JavaScript/TypeScript, use loose equality (== null) as a standard idiom for a 'nullish' check that covers both null and undefined.

Use nullish + empty-string checks instead of truthy checks so a valid 0
for temperature, topP, or the penalties is not dropped. Addresses review
feedback.
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