Repository navigation
feat(qwenwork): add QwenWork in-process provider (global + CN regions) - #301
Open
shenyushun wants to merge 9 commits into
Open
shenyushun wants to merge 9 commits into
shenyushun wants to merge 9 commits into
Conversation
added 9 commits
October 15, 2026 22:22
Device-flow login with PKCE, lazy token refresh with rotation, COSY-signed chat (plain JSON agent_chat_generation), wrapped-SSE translation to OpenAI chunks, live qwork model catalog, account-context quota, error taxonomy incl. quota code 14018 and model_not_available, and credential import for both the canonical and qwenwork2api shapes. Regions: global (qwenwork.ai) and cn (qwenwork.cn).
Adds the QwenWork descriptor (global/cn regions, in-process, OAuth) to the provider registry, registers the adapter in app assembly, and admits the qwenwork/ model prefix in executor prepare and console model settings. Architecture guard now lists qwenwork as a concrete provider.
Provider family label, geometric QwenworkMark (no trademark art), global/cn account types with single-use-link hints, qwenwork-oauth-v1 import default, and the qwenwork/ prefix hint. Static bundle resynced.
…frame errors Final-review fixes: concurrent near-expiry callers now share one refresh round-trip (the rotated refresh token is single-use; a second exchange reads session-dead and disables the account). The non-stream aggregate merges fragmented tool-call deltas by index instead of keeping the last fragment. Quota code 14018 and the model-unavailable text classify even inside 200-class wrapper frames, with quota frames mapping to 402.
…d zhipu First streamed chunk now carries delta.role so strict OpenAI SDKs recognize the assistant turn. A trailing error frame wins over partial content in both paths (matching the JS reference): non-stream returns the classified error, stream keeps the error object as the terminal event with no synthetic finish_reason after it. Architecture guard's concrete-provider list now includes zhipu.
…mports Refresh: the single-flight leader now reloads the stored credential before exchanging (a stale caller snapshot replaying a consumed refresh token read as session-dead and disabled the account), and the exchange runs on a detached context with its own timeout so a cancelled request cannot fail the waiters or lose the rotated pair. Streams: an error-only first frame now fails over before any client byte is relayed, and in-stream error chunks carry code/kind/status so the gateway classifier keeps the provider verdict (quota 14018, auth) instead of re-guessing unavailable. Chunks get a per-request id and created timestamp; content and an error in the same frame are relayed content-first. Imports: credentials without a refresh token skip the exchange instead of being marked login_required; a missing uid is filled from userinfo on Probe and Refresh; millisecond expiries normalize to seconds. Also: model catalog keyed per gateway, max_tokens clamped to the catalog output limit, the chat path reads the account row once, oversized non-stream bodies fail loudly (upstream_body_too_large), quota code 14018 matches only on the code field, and abandoned login states are dropped on StartLogin.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
qwenworkprovider: an in-process adapter for QwenWork (千问办公 / QwenWork international), with two regions under one family —global(gateway.qwenwork.ai, default) andcn(gateway.qwenwork.cn), following the Qoder/WorkBuddy region pattern. No changes to the Qoder provider or worker.agent_chat_generation(same RSA key as Qoder,qworkscene, signed path without/algo); the wrapped upstream SSE is relayed as OpenAI chunks with tool-call delta merging, per-request chunk ids, and classified in-stream errors (code/kind/status carried for the gateway classifier).qworkcatalog with per-gateway cache; quota fromaccount-context(credits, plan).qwenwork/model prefix in executor prepare and console model settings./v1/messages,/v1/responses, quota display, and wrong-model requests that do not cool the account. The CN region follows the desktop bundle configuration and is not yet verified with a real CN account (noted in the changelog and console hint).Test plan
go test ./...go vet ./...go test -race ./...cd worker && npm testcd frontend && npm run build && npm run lintchangelog/unreleased/qwenwork-provider.md(bilingual, matching bullets)