Skip to content

fix(openai-shim): restore reasoning support for proxy and localhost providers - #1155

Closed
JoaoPedroCampanari wants to merge 8 commits into
Twigpine:mainfrom
JoaoPedroCampanari:fix/reasoning-content-dead-flag
Closed

JoaoPedroCampanari wants to merge 8 commits into
Twigpine:mainfrom
JoaoPedroCampanari:fix/reasoning-content-dead-flag

Conversation

@JoaoPedroCampanari

@JoaoPedroCampanari JoaoPedroCampanari commented May 13, 2026 •

Copy link
Copy Markdown

Fixes reasoning model compatibility issues for OpenAI-compatible localhost/proxy setups.

Previously, providers that require reasoning_content (DeepSeek, MiMo, Moonshot/Kimi, ZAI, etc.) could fail with:

400 OpenAI API error 400: data:{"error":{"code":"400","message":"Param Incorrect","param":"The reasoning_content in
the thinking mode must be passed back to the API.","type":""}}

during multi-turn agent workflows.

This especially affected local proxy/key-router setups such as:

  • localhost OpenAI-compatible endpoints
  • GRouter
  • reverse proxy gateways

Root Cause

Two independent issues caused the failures:

  1. requireReasoningContentOnAssistantMessages was never consumed

The flag existed in provider descriptors and was configured by:

  • DeepSeek
  • Moonshot/Kimi
  • MiMo
  • ZAI
  • kimi-code

However, the OpenAI shim message conversion pipeline never actually used the flag.

As a result, assistant messages could lose reasoning_content during agent execution.

  1. treatAsLocal bypassed model inference

The treatAsLocal code path skipped model-name-based config inference entirely.

This prevented localhost/proxy endpoints from inheriting reasoning-specific behavior even when the routed model was
clearly identifiable, such as:

  • mimo-v2.5-pro
  • deepseek-reasoner
  • other reasoning-capable providers

Changes

src/services/api/openaiShim.ts

Implemented 5 fixes in convertMessages():

  • Pass requireReasoningContentOnAssistantMessages into the conversion pipeline
  • Attach reasoning_content: '' to assistant messages when required by provider config
  • Remove the toolUses.length > 0 restriction so plain-text assistant messages are also handled
  • Preserve reasoning_content during assistant-message coalescing
  • Add fallback reasoning_content to synthetic assistant messages created during tool/user alternation
  • Add handling for non-array-content assistant messages

src/integrations/runtimeMetadata.ts

  • Merge reasoning-related fields from inferRemoteModelOpenAIShimConfig() into the treatAsLocal branch
  • Allows localhost/proxy endpoints to inherit correct reasoning behavior from model-name inference

Provider Impact

Fixes reasoning-agent failures for:

  • DeepSeek
  • Moonshot/Kimi
  • MiMo
  • ZAI
  • future providers using requireReasoningContentOnAssistantMessages: true

Also enables reasoning models to work correctly through:

  • localhost OpenAI-compatible endpoints
  • proxy routers
  • API gateways

No behavior changes for providers that do not use the flag.

Tested

  • bun run build ✅
  • bun run smoke ✅
  • bun test src/services/api/openaiShim → 104 pass / 0 fail ✅

Manual validation:

  • MiMo v2.5 Pro via GRouter (localhost:3103) ✅
  • MiMo v2.5 Pro via direct Xiaomi endpoint ✅

Verified:

  • Explore agents
  • background agents
  • multi-turn reasoning flows
  • reasoning-content persistence

Follow-up

Some reasoning providers (Qwen/QwQ/GLM/etc.) are not yet included in inferRemoteModelOpenAIShimConfig().

Once entries are added, the treatAsLocal fix ensures they will automatically work through localhost/proxy setups as
well.

Summary by CodeRabbit

  • New Features

    • Extended support for additional AI model families with optimized configuration handling.
    • Improved reasoning content preservation during message processing and model interactions.
  • Bug Fixes

    • Fixed configuration value overriding to preserve explicitly set token field settings.
    • Enhanced reasoning content persistence across message operations.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Findings

  • [P2] Keep non-empty reasoning_content when coalescing assistant messages
    src/services/api/openaiShim.ts:762
    The new coalescing logic overwrites an existing non-empty reasoning_content whenever the following assistant message has the empty-string fallback. For example, a Moonshot/Kimi history with an assistant tool call that includes a thinking block, followed by another assistant text message before the tool result, is converted into one assistant message whose reasoning_content is "" instead of the original thinking text. That still sends a tool-call assistant message without the reasoning continuity these providers require, so the PR's target proxy/reasoning workflow can still hit the 400 this is meant to fix. Please keep the previous non-empty value when the incoming value is only the fallback, or otherwise merge in a way that does not discard the real reasoning text.

@JoaoPedroCampanari

Copy link
Copy Markdown
Author

@jatmn I've addressed your feedback in commit 81a8c02 — the coalescing logic now preserves non-empty reasoning_content when the incoming value is an empty fallback. Please re-review.

jatmn
jatmn previously approved these changes May 13, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for following up on the earlier review. The requested reasoning_content coalescing fix looks addressed now.

No remaining issues here, LGTM.

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

Review summary

Thanks for the follow-up here. The dead requireReasoningContentOnAssistantMessages path is now wired into the shim, and the prior coalescing issue looks fixed. I found one remaining scope/correctness gap around the advertised local-proxy provider coverage.

Findings

  • src/integrations/runtimeMetadata.ts:218 - Local/proxy inference does not cover advertised MiMo or Z.AI/GLM models.
    Impact: The PR says localhost/proxy setups like GRouter work for models such as mimo-v2.5-pro and also lists Z.AI, but inferRemoteModelOpenAIShimConfig() still only recognizes deepseek, kimi, and moonshot. In a local proxy context, mimo-v2.5-pro, GLM-5.1, and zai/glm-5.1 resolve to only { maxTokensField: "max_tokens" }, so they still do not get preserveReasoningContent, requireReasoningContentOnAssistantMessages, or reasoningContentFallback.
    Suggested fix: Add model-name inference for the advertised providers, with focused tests for local proxy models, or narrow the PR description/provider claims to DeepSeek and Kimi/Moonshot only.

Validation

  • bun test src/services/api/openaiShim.test.ts passed: 93 tests.
  • bun test src/integrations/routeMetadata.test.ts src/integrations/compatibility.test.ts src/services/api/providerConfig.local.test.ts passed: 40 tests.
  • bun run build passed.
  • Manual local-proxy config check showed deepseek-reasoner and kimi-k2.6 infer reasoning config, but mimo-v2.5-pro, GLM-5.1, and zai/glm-5.1 do not.

@JoaoPedroCampanari

Copy link
Copy Markdown
Author

@techbrewboss I've addressed your feedback in commit 95f7fee — inferRemoteModelOpenAIShimConfig() now covers MiMo and GLM/Z.AI models in the local/proxy path. Could you re-review?

Changes:

  • mimo → preserveReasoningContent, requireReasoningContentOnAssistantMessages, reasoningContentFallback
  • glm / zai/glm → same reasoning config
  • Tested with mimo-v2.5-pro, GLM-5.1, and zai/glm-5.1 via local proxy — all now infer correct reasoning behavior

@JoaoPedroCampanari
JoaoPedroCampanari requested a review from jatmn May 14, 2026 19:22

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

Review summary

Thanks for following up on the local/proxy reasoning-content path. The dead requireReasoningContentOnAssistantMessages flag is now wired into the shim and the MiMo/GLM local-proxy inference gap is addressed, but I found one direct-provider regression that should block merge.

Findings

  • src/integrations/runtimeMetadata.ts:166 - MiMo model-name inference overrides the direct Xiaomi MiMo route’s token field.
    Impact: direct https://api.xiaomimimo.com/v1 requests for mimo-v2.5-pro now send max_tokens instead of the descriptor-required max_completion_tokens. This breaks the existing xiaomi mimo route uses api-key auth header and max_completion_tokens test and contradicts the PR’s “No behavior changes” claim for direct providers.
    Suggested fix: keep the new MiMo/GLM inference scoped to local/proxy or generic OpenAI-compatible routing, or avoid returning maxTokensField: 'max_tokens' from MiMo model-name inference so the Xiaomi descriptor can continue to win.

Validation

  • Fetched PR Gitlawb/openclaude#1155 into an isolated worktree at commit 95f7fee.
  • Ran bun test src/services/api/openaiShim.test.ts src/integrations/routeMetadata.test.ts src/integrations/compatibility.test.ts src/services/api/providerConfig.local.test.ts with the repo’s existing node_modules symlinked into the temporary worktree.
  • Result: 136 pass, 1 fail.
  • Failing test: xiaomi mimo route uses api-key auth header and max_completion_tokens.

@Vasanthdev2004

Copy link
Copy Markdown
Collaborator

Blockers

  1. MiMo model-name inference overrides direct Xiaomi route's token field — inferRemoteModelOpenAIShimConfig() now returns maxTokensField: 'max_tokens' for MiMo models, which overrides the descriptor-required max_completion_tokens for the direct Xiaomi endpoint. This breaks the existing test and contradicts the "No behavior changes" claim for direct providers.

Non-Blocking

  • PR went through multiple review rounds — coalescing fix and MiMo/GLM inference were addressed, but the direct-provider regression remains.

Looks Good

  • Fixes real reasoning support for proxy/localhost providers
  • Wires requireReasoningContentOnAssistantMessages into the shim
  • Covers DeepSeek, Kimi/Moonshot, MiMo, GLM/Z.AI
  • 104 tests passing in openaiShim

Verdict: Changes Requested — direct-provider regression must be fixed before merge.

@JoaoPedroCampanari
JoaoPedroCampanari force-pushed the fix/reasoning-content-dead-flag branch from b818715 to 6dc6e84 Compare May 16, 2026 12:04

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

Review summary

The reasoning-content/runtime fix looks useful and the focused provider tests pass on the current PR head. I found one remaining scope issue: the branch includes release-please version/changelog output unrelated to this fix.

Findings

  • package.json:3, .release-please-manifest.json:2, CHANGELOG.md:3 - Unrelated release-please version/changelog changes are included.
    Impact: This reasoning-content PR now also bumps the package to 0.12.1 and adds changelog entries for unrelated PRs #1191 and #1204. That mixes release automation output into a provider/runtime fix and can confuse the release process or make this PR appear to publish unrelated work.
    Suggested fix: Drop the release-please commit/files from this branch and keep the PR limited to the shim/runtime changes.

Validation

  • Fetched PR head 1348e0a into an isolated worktree.
  • bun test src/services/api/openaiShim.test.ts src/integrations/routeMetadata.test.ts src/integrations/compatibility.test.ts src/services/api/providerConfig.local.test.ts passed: 141 tests.
  • bun run build passed.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for following up on the earlier reviews. The requested reasoning_content coalescing fix still looks addressed, and the direct Xiaomi MiMo token-field regression is covered now. I found one remaining issue below.

Findings

  • [P2] Drop unrelated release-please output from this branch
    package.json:3, .release-please-manifest.json:2, CHANGELOG.md:3
    This reasoning-content fix now also bumps the package version to 0.12.1 and adds changelog entries for unrelated PRs #1191 and #1204. That mixes release automation output into a provider/runtime fix, which can confuse the release process and make this PR appear to publish unrelated work. Please remove the release-please commit/files from this branch and keep the PR scoped to the shim/runtime changes.

@gnanam1990

Copy link
Copy Markdown
Collaborator

Confirmed @jatmn's and @techbrewboss's point against the branch — they've both landed on the same single remaining issue. The reasoning-content/runtime fix itself looks addressed (both reviewers agree), but the branch also carries release-please output: package.json bumped to 0.12.1 and CHANGELOG.md / .release-please-manifest.json entries for unrelated PRs #1191 and #1204. That mixes release automation into a provider/runtime fix and can confuse the release process. Dropping the release-please commit/files and keeping this scoped to runtimeMetadata.ts / openaiShim.ts clears it. Thanks — happy to re-review as soon as the branch is trimmed.

…serve reasoning through local proxies

What changed:
`requireReasoningContentOnAssistantMessages` was defined in descriptors.ts
and set by five vendor configs (deepseek, moonshot, mimo, zai, kimi-code)
but never consumed in the OpenAI shim's message conversion pipeline. This
meant any provider that required reasoning_content on assistant messages
would get a 400 error from the API ("reasoning_content must be passed back
to the API") whenever the flag was the only source of truth.

Additionally, the `treatAsLocal` code path in runtimeMetadata.ts bypassed
model-name-based config inference entirely, so local proxies (e.g. key
routers like grouter) forwarding to remote reasoning models never received
reasoning-related config even when the model name clearly indicated a
reasoning provider.

Why it changed:
- The flag was a dead config — set but never read — causing 400 errors for
  all five vendors that rely on it
- Local proxies that forward to reasoning providers need the same config as
  direct connections; the model name (e.g. "mimo-v2.5-pro") is sufficient
  signal regardless of whether the base URL is localhost or remote
- The empty-string reasoning_content fallback was gated on toolUses.length > 0,
  so plain-text assistant messages without tool calls were missing the field
- The coalescing pass silently dropped reasoning_content when merging
  consecutive assistant messages
- Synthetic assistant messages injected during tool→user gaps and non-array
  content assistant messages never received reasoning_content

User/developer impact:
- Fixes 400 errors for DeepSeek, Moonshot/Kimi, MiMo, ZAI, and any future
  vendor that sets requireReasoningContentOnAssistantMessages: true
- Enables reasoning models to work through local proxies/key routers without
  manual config
- No behavior change for providers that do not set the flag (all defaults
  remain false/undefined)

Checks run:
- bun run build — clean
- bun run smoke — pass
- bun test src/services/api/openaiShim — 104 pass, 0 fail
When coalescing consecutive assistant messages, an empty
reasoning_content fallback ("") would overwrite a non-empty
thinking text from a previous message. Now we only overwrite
when the incoming value is non-empty or the existing value
is already empty/undefined.
inferRemoteModelOpenAIShimConfig() only recognized deepseek,
kimi, and moonshot. When using a local proxy (e.g. GRouter)
with mimo-v2.5-pro or GLM-5.1, the function returned undefined,
so these models got no reasoning config even with the treatAsLocal
merge fix. Now mimo and glm patterns are recognized and return
the same reasoning config their vendor files define.
InferRemoteModelOpenAIShimConfig for mimo and glm returned
maxTokensField and removeBodyFields, which overrode the Xiaomi
MiMo vendor descriptor's max_completion_tokens when the direct
route was used. Model-name inference should only return reasoning-
related fields (preserveReasoningContent, requireReasoningContent,
reasoningContentFallback, thinkingRequestFormat) so the descriptor
remains the source of truth for transport fields like maxTokensField.
mergeOpenAIShimConfig now checks for a descriptor-level maxTokensField
before applying the model-inferred value. This prevents direct providers
(e.g. Xiaomi with max_completion_tokens) from being overridden by
inference results that default to max_tokens.

Gateway routes without a descriptor still receive the inferred value.
The treatAsLocal code path was dropping removeBodyFields from the
model-inference config. For DeepSeek/Kimi models, inference returns
removeBodyFields: ['store'] which was silently lost for local proxies.

Currently mitigated by the isLocal store-stripping check, but this
ensures future removeBodyFields entries are also preserved.
MiMo's API expects `max_completion_tokens` (matching its vendor descriptor),
but the model-name inference was not setting maxTokensField. When going
through a localhost proxy (treatAsLocal path), the default `max_tokens`
was applied instead, causing the API to ignore the token limit and
terminate responses prematurely.

Also adds missing removeBodyFields: ['store'] for both MiMo and GLM
to match the pattern used by DeepSeek and Kimi inference configs.
The treatAsLocal code path hardcoded maxTokensField to 'max_tokens',
which broke providers like MiMo that require 'max_completion_tokens'
even when accessed through a local proxy (e.g. GRouter).

Now checks if remoteModelInferredConfig has a maxTokensField before
falling back to 'max_tokens', matching the pattern already used for
reasoning fields.
@JoaoPedroCampanari
JoaoPedroCampanari force-pushed the fix/reasoning-content-dead-flag branch from 1348e0a to 103130e Compare May 17, 2026 12:17
@JoaoPedroCampanari
JoaoPedroCampanari requested a review from jatmn May 17, 2026 12:21

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for trimming the branch. The release-please output is gone now, and this is scoped back to the shim/runtime changes.

No issues here, LGTM.

WesleySouzaSilva added a commit to WesleySouzaSilva/openclaude that referenced this pull request May 24, 2026
…e in generic OpenAI provider test (Twigpine#1228)

Fix the deserializeMessagesWithInterruptDetection test so it
correctly expects stripped thinking blocks for generic OpenAI-
compatible providers, and passes regardless of host environment
variables.

Problem
━━━━━━━
Reviewer jatmn flagged a P1 blocker: the "third-party provider" test
branch mocks getAPIProvider() as 'openai' but does not clear the host
environment. When the developer's shell has:

  OPENAI_BASE_URL=https://api.deepseek.com
  OPENAI_MODEL=deepseek-chat

…the test silently passes locally because inferRemoteModel-
OpenAIShimConfig('deepseek-chat') activates preserveReasoningContent
via the includes('deepseek') branch. On CI or clean machines, the
assertion expecting preserved thinking blocks fails.

This was the only failing test across the 3 modified files, making
the PR's stated "All 108 tests pass" claim incorrect for the current
code.

Fix
━━━━
1. Delete process.env.OPENAI_BASE_URL and OPENAI_MODEL before the
   generic OpenAI test block, so shouldPreserveThinkingBlocks-
   ForProviderReplay() correctly returns false regardless of what
   the developer has in their shell.
2. Update the assertion to expect stripped thinking blocks
   ([{ type: 'text', text: 'Here is my answer.' }]) — the correct
   behavior for a provider without preserveReasoningContent.
3. Add a MiMo branch below (OPENAI_MODEL=mimo-v2.5-pro) that asserts
   thinking blocks ARE preserved when preserveReasoningContent is
   active, covering both sides of the conditional.
4. Update inline comments to clarify why env vars must be cleared
   and why thinking blocks are stripped vs preserved across each
   provider branch.

Verification
━━━━━━━━━━━━
All 3 affected test files pass with 0 failures:

  bun test src/utils/conversationRecovery.hooks.test.ts  → 2/2 pass
  bun test src/utils/conversationRecovery.test.ts        → 5/5 pass
  bun test src/services/api/openaiShim.test.ts          → 107/107 pass

Related reasoning_content PRs (same domain, independent fixes):
  Twigpine#666  — preserve reasoning content on tool call replays (draft)
  Twigpine#783  — consolidate 3P provider compatibility fixes (merged)
  Twigpine#1155 — restore reasoning support for proxy/localhost (open)
  Twigpine#1201 — tighten reasoning_content heuristic (merged)
@jatmn jatmn mentioned this pull request May 26, 2026
@jatmn
jatmn requested review from anandh8x and auriti May 26, 2026 00:09
@jatmn
jatmn requested review from gnanam1990 and removed request for gnanam1990 June 2, 2026 05:56
@jatmn jatmn linked an issue Jun 2, 2026 that may be closed by this pull request
@JoaoPedroCampanari

Copy link
Copy Markdown
Author

@jatmn Are there any other adjustments needed before this can be approved?

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the update. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.

@jatmn

jatmn commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 6, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026 •

Copy link
Copy Markdown
Contributor

Lost in the diff? Review this PR in Change Stack to follow the change map from intent to exact ranges.

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e573c63e-4312-4356-a981-e73bff322d52

📥 Commits

Reviewing files that changed from the base of the PR and between 0fba154 and 103130e.

📒 Files selected for processing (2)
  • src/integrations/runtimeMetadata.ts
  • src/services/api/openaiShim.ts

📝 Walkthrough

Walkthrough

This PR expands reasoning-content support for additional model families (mimo, glm) by updating remote-model inference, enforcing descriptor-level configuration precedence, and adding reasoning-content preservation across message conversion and coalescing pipelines.

Changes

Reasoning Content and Remote Model Support

Layer / File(s) Summary
Remote model family inference
src/integrations/runtimeMetadata.ts
inferRemoteModelOpenAIShimConfig recognizes mimo and glm model families, enabling reasoning preservation with thinkingRequestFormat: 'deepseek-compatible', selecting appropriate token fields, and removing the store body field.
Config merging precedence and local context resolution
src/integrations/runtimeMetadata.ts
mergeOpenAIShimConfig preserves descriptor-level maxTokensField over inferred config, and resolveOpenAIShimRuntimeContext applies remote-model inference to local proxies with reasoning fields and body-field removals instead of hardcoding max_tokens.
Message conversion reasoning content support
src/services/api/openaiShim.ts
convertMessages adds requireReasoningContentOnAssistantMessages option, and assistant-message construction paths emit empty reasoning_content when required, including synthetic messages during tool-execution interruption and fallback cases.
Message merging preservation and config propagation
src/services/api/openaiShim.ts
Message coalescing preserves non-empty reasoning_content across consecutive assistant-message merges, and the OpenAI shim request path propagates requireReasoningContentOnAssistantMessages into convertMessages.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A mimo hops, a glm gleams bright,
Their reasoning preserved through the night,
Config cascades with precedence true,
Messages coalesce, yet reasoning stays new,
🐰 Thinking content hops, never askew!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title accurately reflects the main purpose of the PR: fixing reasoning support for OpenAI-compatible providers via proxy and localhost setups.
Description check ✅ Passed The PR description covers all major template sections with comprehensive details about what changed, root causes, testing results, and provider impact.
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 unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@jatmn

jatmn commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

@kevincodex1 please merge

@jatmn

jatmn commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Closing as superseded by the merged fixes in #1253 and #1228, which cover the MiMo/reasoning-content paths this PR was targeting.

@jatmn jatmn closed this Jun 16, 2026
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.

api错误

5 participants