Skip to content

🔨 chore(model-runtime): support azure openai router runtime#13823

Merged
tjx666 merged 17 commits into
canaryfrom
fix/azure-openai-router-runtime
Apr 25, 2026
Merged

🔨 chore(model-runtime): support azure openai router runtime#13823
tjx666 merged 17 commits into
canaryfrom
fix/azure-openai-router-runtime

Conversation

@tjx666

@tjx666 tjx666 commented Apr 14, 2026

Copy link
Copy Markdown
Member

💻 Change Type

  • ✨ feat
  • 🐛 fix
  • ♻️ refactor
  • 💄 style
  • 👷 build
  • ⚡️ perf
  • ✅ test
  • 📝 docs
  • 🔨 chore

🔗 Related Issue

N/A

🔀 Description of Change

  • add a dedicated azureopenai RouterRuntime apiType instead of routing Azure OpenAI traffic through azureai
  • support per-model apiVersionMapping resolution in RouterRuntime provider options
  • update Azure OpenAI runtime to align pricing/provider propagation with OpenAI-compatible routing, request Azure usage in streaming mode, and strip unsupported GPT-5 reasoning params
  • add regression tests for Azure OpenAI runtime payload handling and RouterRuntime apiVersion mapping
  • include the workspace settings update already made on this branch

🧪 How to Test

  • Tested locally
  • Added/updated tests
  • No tests needed

Manual verification:

  • route gpt-5.4 through azureopenai in local router runtime config
  • verify Azure OpenAI streaming succeeds without fallback
  • verify the final Azure stream chunk contains usage
  • verify computeChatPricing and createCostTracker record non-zero spend for gpt-5.4@lobehub

Automated coverage added:

  • packages/model-runtime/src/providers/azureOpenai/index.test.ts
  • packages/model-runtime/src/core/RouterRuntime/createRuntime.test.ts

Note:

  • package-level Vitest coverage for the affected suites is currently blocked by an existing zod initialization issue during model-bank import in this environment

📸 Screenshots / Videos

Before After
N/A N/A

📝 Additional Information

  • this PR keeps Azure AI (azureai) and Azure OpenAI (azureopenai) routing semantics separate to avoid endpoint/runtime mismatches
  • apiVersionMapping allows chat and embeddings on the same Azure resource to use different API versions when required

@sourcery-ai sourcery-ai Bot left a comment

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.

We've reviewed this pull request using the Sourcery rules engine

@vercel

vercel Bot commented Apr 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lobehub Ready Ready Preview, Comment Apr 25, 2026 8:03am

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1f1a244e8b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +93 to +95
const unsupportedReasoningParams = isAzureReasoningModel(model)
? {}
: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve sampling controls when reasoning is disabled

This logic strips temperature, top_p, logprobs, and related fields for every model matched by isAzureReasoningModel, regardless of reasoning_effort. For requests such as gpt-5.* with reasoning_effort: 'none', user sampling settings are silently dropped because unsupportedReasoningParams is {}, which can change output behavior and prevents users from controlling determinism/creativity in that mode.

Useful? React with 👍 / 👎.

Comment on lines +451 to +455
const runtimeModel = router.models?.[0] ?? '';
const { id: resolvedApiType, runtime } = await this.createRuntimeFromOption(
router,
routerOptions[0],
runtimeModel,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid model-order-dependent API version in models()

The models() path now feeds router.models?.[0] into createRuntimeFromOption, so apiVersionMapping resolution depends on the first model’s position in config rather than an explicit discovery version. Because models() is not tied to a specific model request, this can initialize a runtime with a preview API version intended for one model and make model discovery behavior change when the model array order changes.

Useful? React with 👍 / 👎.

@codecov

codecov Bot commented Apr 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.83333% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.57%. Comparing base (043d2a8) to head (6b91899).
⚠️ Report is 11 commits behind head on canary.

Additional details and impacted files
@@             Coverage Diff             @@
##           canary   #13823       +/-   ##
===========================================
- Coverage   86.12%   67.57%   -18.56%     
===========================================
  Files         610     2192     +1582     
  Lines       51406   188837   +137431     
  Branches     8689    22458    +13769     
===========================================
+ Hits        44273   127603    +83330     
- Misses       7005    61106    +54101     
  Partials      128      128               
Flag Coverage Δ
app 60.60% <94.44%> (?)
database 92.24% <ø> (ø)
packages/agent-runtime 79.82% <ø> (ø)
packages/context-engine 83.23% <ø> (ø)
packages/conversation-flow 92.40% <ø> (ø)
packages/file-loaders 87.02% <ø> (ø)
packages/memory-user-memory 74.74% <ø> (ø)
packages/model-bank 99.89% <ø> (ø)
packages/model-runtime 84.31% <90.54%> (+0.25%) ⬆️
packages/prompts 70.14% <ø> (ø)
packages/python-interpreter 92.90% <ø> (ø)
packages/ssrf-safe-fetch 0.00% <ø> (ø)
packages/utils 88.41% <ø> (ø)
packages/web-crawler 88.66% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Store 67.16% <ø> (∅)
Services 53.24% <93.75%> (∅)
Server 66.62% <100.00%> (∅)
Libs 53.30% <ø> (∅)
Utils 80.04% <ø> (-13.43%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@tjx666 tjx666 force-pushed the fix/azure-openai-router-runtime branch from 2cbe45f to 3e3e7cf Compare April 22, 2026 10:51
@tjx666 tjx666 force-pushed the fix/azure-openai-router-runtime branch from 0aace8c to 995fadd Compare April 23, 2026 08:43
@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Apr 23, 2026
@tjx666 tjx666 force-pushed the fix/azure-openai-router-runtime branch from 995fadd to 504bc2d Compare April 23, 2026 09:46
@tjx666 tjx666 force-pushed the fix/azure-openai-router-runtime branch from 504bc2d to 1c3f583 Compare April 23, 2026 09:56
@tjx666 tjx666 force-pushed the fix/azure-openai-router-runtime branch from 1c3f583 to 79e6513 Compare April 24, 2026 08:10
@tjx666 tjx666 force-pushed the fix/azure-openai-router-runtime branch from 79e6513 to b076542 Compare April 24, 2026 08:51
tjx666 added 10 commits April 25, 2026 11:24
- rename `unsupportedReasoningParams` to `supportedSamplingParams` so the
  variable name reflects its actual role (params passed through for
  non-reasoning models) and drop the misleading `_` prefix on destructured
  params that were re-read
- tighten `normalizeAzureBaseURL` path check to use segment-boundary matching
  so values like `/openaifoo` no longer falsely satisfy the already-has-`openai`
  condition and get rewritten
- hoist `convertImageUrlToFile` dynamic import out of the two mutually
  exclusive image-input branches to avoid duplicate imports on the hot path
- strengthen `createRuntime.test.ts` "preserve unsupported version fields"
  assertion so it explicitly verifies `apiVersionMapping` is forwarded to
  every constructor call rather than relying on `objectContaining` that
  silently ignores the field
…omOption

The `model` parameter was threaded through `createRuntimeFromOption` as
scaffolding for per-model `apiVersionMapping` resolution, but LOBE-7220
drops the apiVersion dependency entirely in favor of the Azure
`/openai/v1/` endpoint. Remove the dead signature noise and the
companion `apiVersionMapping` preservation test so the router contract
no longer implies behavior that will never ship.

Refs: LOBE-7220
@tjx666 tjx666 merged commit 697ac3b into canary Apr 25, 2026
35 checks passed
@tjx666 tjx666 deleted the fix/azure-openai-router-runtime branch April 25, 2026 08:08
@arvinxx arvinxx mentioned this pull request Apr 27, 2026
arvinxx added a commit that referenced this pull request Apr 27, 2026
# 🚀 LobeHub v2.1.53 (20260427)

**Release Date:** April 27, 2026
**Since v2.1.52:** 194 merged PRs · 17 contributors

> Introduce Heterogeneous Agent — Claude Code and Codex run as
first-class desktop runtimes, paired with a new Agent Signal package,
sharper desktop UX, and a wave of flagship model additions.

---

## ✨ Highlights

- **Introduce Heterogeneous Agent** — Claude Code and Codex run as
first-class desktop agents: subagent rendering, partial-message
streaming, multi-turn resume, terminal error surfacing, rich tool
inspectors, and runtime polish. (#14162, #13754, #14067, #14001, #13970,
#13942)
- **Screen capture & Quick Chat tray** — New desktop screen capture
overlay (macOS permission-gated) with Quick Chat tray and upload
pipeline improvements; chat input auto-focuses on overlay mount.
(#13818, #14097, #14105)
- **Desktop topic & tab UX** — Dedicated topic popup window with
cross-window sync, Cmd+W/Cmd+T tab shortcuts, TabBar polish, recent
working directories expanded to 20, and human approval notifications.
(#13957, #13983, #13972, #14036, #14092)
- **Git workflow built-in** — One-click pull/push from the branch chip,
ahead/behind badge, and submodule/worktree repo detection. (#14041,
#13980, #13978)
- **Agent Signal package** — New `@lobechat/agent-signal` runtime for
dynamic memory feedback signals, with OTel metrics and self-iteration in
Lab. (#14157, #14170, #14159, #14169, #14187)
- **New models** — Claude Opus 4.7 with `xhigh` effort tier, GPT-5.5,
DeepSeek V4 Flash/Pro with reasoning slider, Kimi K2.6, MiMo-V2.5/Pro,
gpt-image-2, Qwen3.6 Flash/Plus, and Pixverse-c1. (#13903, #14147,
#14114, #14004, #14089, #14039, #13923)
- **New providers** — OpenCode Zen, OpenCode Go, and Azure OpenAI Router
runtime. (#13943, #14064, #13823)
- **Mobile settings overhaul** — Full settings menu and responsive
profile layout for mobile. (#14019)

---

## 🏗️ Heterogeneous Agent

- Claude Code runtime, working-directory awareness, and sidebar polish.
(#13970)
- CC subagent rendering with persistent streamed text; parallel-tool
orphan fix. (#14001, #13968, #14024)
- Per-step usage persisted to each step assistant message. (#13964)
- Per-phase workflow expand defaults; full-expand toggle with
three-level expansion. (#14171, #13906)
- Hetero-mode actions bar; tool inspector polish. (#13963, #14034,
#14030)
- Codex desktop integration with rich tool rendering and devtools
preview. (#14067, #14100)
- Codex terminal error surfacing and CLI output tracing. (#14166)
- Tighten `isCanUseVision` default and add aggregator fallback. (#14172)
- Persist `ccSessionId` in topic metadata for CC multi-turn resume.
(#13902)
- CC account card, topic filter, and integration polish. (#13955,
#13942, #13950)
- Token-level deltas streamed via `--include-partial-messages`. (#13929)

---

## 🧠 Agent Signal & Self-Iteration

- New `@lobechat/agent-signal` package with dynamic feedback signals.
(#14157)
- AgentSignalRuntime wired through agent-tracing and observability-otel
metrics. (#14170, #14159)
- Self-iteration feature flag added to Lab; front-side flag check.
(#14169, #14186)
- Signal policy for receiving memory feedback dynamically. (#14187)

---

## 💬 Conversation

- Queue follow-up sends during running CC turns. (#14179)
- Persist per-topic chat scroll position; pin user message + fold long
messages. (#14191, #14056)
- Inline resend when editing last user message. (#14080)
- Disable first-block markdown streaming to prevent flicker. (#14193,
#13904)
- Prevent Markdown stream replay when vlist remounts streaming items.
(#14086)
- Stop repinning after manual scroll; unify scroll-to-user + spacer
hooks. (#14099, #14132)

---

## 📱 Platforms & Integrations

### Desktop / Electron

- Screen capture overlay, Quick Chat tray, and upload pipeline
improvements. (#13818)
- macOS permission gate for screen capture; auto-focus chat panel input.
(#14097, #14105)
- Dedicated topic popup window with cross-window sync. (#13957)
- TabBar polish: `+` button for new topic, dark theme blend, close icon
by default. (#13972, #14203, #13973)
- Recent working directories expanded from 5 to 20; submodule/worktree
repo detection. (#14036, #13978)
- Cmd+W / Cmd+T tab shortcuts and global shortcut consolidation.
(#13983, #13880)
- Linux icon configuration; human approval desktop notifications.
(#14042, #14092)

### Git Workflow

- One-click pull/push from branch chip; ahead/behind badge with
refactored GitCtr. (#14041, #13980)

### Mobile

- Full settings menu and responsive profile layout. (#14019)
- Agent route added to mobile router; mobile agent topic route
registered. (#14103, #14158)
- Session list skeleton row layout corrected. (#14040)

### Bot / Messaging

- DM strategy support; bot emoji and markdown render optimization.
(#14201, #14091, #14140)
- Slack webhook fix; bot platform setup guide reference. (#14052,
#14121)

---

## 🤖 Models & Providers

### New models

- **Claude Opus 4.7** with `xhigh` effort tier; strip temperature/top_p.
(#13903, #13909)
- **GPT-5.5**. (#14147)
- **DeepSeek V4** Flash/Pro cards with reasoning slider; cache-hit and
Pro discount pricing. (#14114, #14209, #14196, #14131)
- **Kimi K2.6** model with LobeHub-hosted card. (#14004, #14006)
- **MiMo-V2.5 / V2.5-Pro**. (#14089)
- **gpt-image-2**, **Qwen3.6 Flash/Plus**, **Pixverse-c1**. (#14039,
#13923)

### New providers

- **OpenCode Zen** and **OpenCode Go** with env-var support. (#13943,
#14064)
- **Azure OpenAI Router** runtime support. (#13823)
- Model alias mapping for image and video runtimes. (#13896)
- Seedance video models migrated to Dreamina. (#14144)

### Runtime reliability

- Sanitize invalid tool_call arguments to unbreak strict providers.
(#14033)
- Tolerate null `function.name` in streaming tool_call deltas. (#14139)
- Preserve Gemini 3 `thoughtSignature` in `call_tools_batch`
normalization. (#14032)
- Downgrade `image_url` parts when target model lacks vision. (#14029)
- Preserve Cloudflare provider error context. (#14136)
- Use `safety_identifier` for OpenAI Responses API. (#14148)
- Unwrap underlying PG error in `formatErrorEventData`. (#14038)

---

## 🖥️ User Experience

- **Onboarding** — Preset agent naming suggestions, structured hunk ops
for `updateDocument`, persona analytics snapshot, footer promotion
pipeline, wrap-up button. (#13931, #13989, #13930, #13853, #13934)
- **Document workflow** — Agent documents promoted as primary workspace
panel; history management and compare workflow; web-crawl docs
associated with agent documents. (#13924, #13725, #13893)
- **cmdk** — Agent identity surfaced on topic search results;
topic/message search scoped to current agent. (#14204, #13960)
- **Floating chat panel** and workspace improvements. (#13887)
- **Topic completion status** with dropdown action and filter. (#14005)

---

## 🔧 Tooling

- Redis-backed feature flag provider for runtime config. (#14098)
- Vite upgraded to 8.0.0 with Rolldown strict execution order. (#12720,
#14058)
- `@lobechat/model-bank` automated npm release with provenance. (#14015,
#14017, #14018)
- Skill activation fallback when `activateTools` cannot find identifier.
(#14010)
- Cron tool: timezone and existing jobs injected into system prompt;
clarified `lobe-gtd` and `lobe-cron` descriptions. (#14012, #14013)

---

## 🔒 Security & Reliability

- **Security:** uuid bumped to v14 (advisory). (#14083)
- **Security:** validate avatar URL and scope old-avatar deletion to
owner. (#13982)
- **Security:** clear OIDC sessions on better-auth signout; return 401
(not 500) for expired OIDC JWT. (#13916, #14014)
- **Reliability:** scope pending-approval check to current assistant
turn. (#14182)
- **Reliability:** sanitize heterogeneous-agent attachment cache
filenames. (#13937)
- **Reliability:** reduce subagent task status error noise. (#14026)

---

## 👥 Contributors

Huge thanks to **17 contributors** who shipped **194 merged PRs** this
week.

@hardy · @shaun0927 · @hezhijie0327 · @sxjeru · @arvinxx · @Innei ·
@tjx666 · @lijian · @neko · @rdmclin2 · @AmAzing129 · @sudongyuer ·
@CanisMinor · @rivertwilight

Plus @lobehubbot and renovate[bot] for maintenance.

---

**Full Changelog**:
v2.1.52...v2.1.53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant