Repository navigation
feat(qoder): in-process PAT bridge, reasoning stream, and in-process check-in - #313
Conversation
|
Follow-up fix pushed (f1e7a97): This commit mirrors the worker-path aggregation and the Exceeded override (an available add-on keeps |
caigee-cmd
left a comment
There was a problem hiding this comment.
感谢这次很大的投入!PAT 全进程化、修复 reasoning 流丢失(chat_context)、从原始 /model/list 解析目录,以及新提交里把套餐、资源包、组织资源包三项加总显示额度,都是我们想要的方向,测试覆盖也比较充分。
由于范围较大,合并前需要先处理以下几点:
- Rebase:#312 已合入 main,请 rebase 到最新 main,或点 Update branch,让 diff 只剩本 PR 自己的改动。同时请更新 PR 描述里过时的 "Stacked on #4" 说明。
- 拆分:TTFB 30 秒故障转移和 worker 存活 watchdog(提交 556ce14)与 PAT bridge 无直接关系,请拆成单独的 PR,便于分别评审和回滚。
- 许可证与来源:
qauth/qauth.go和risk.go注明是从 qoder2api 逐字移植的。请在 PR 描述和文件头中写明上游仓库地址、对应的 commit 或版本以及许可证类型,确认许可证允许以本项目的协议再分发,并按要求补充 NOTICE 或版权声明。在这一点确认之前我们无法合并。 - 执行桌面端程序:
risk.go会查找并执行本机 Qoder 安装目录里的umid/runtime-info来获取设备指纹。在服务端执行第三方二进制、并把真实硬件指纹发给上游,存在安全隐患和被风控封号的风险,而且多账号共用同一台机器的指纹也可能导致账号被关联。请删除这部分,统一使用 PAT 派生的身份;如果确实需要保留,请改成默认关闭的显式配置项,并在文档中说明风险。 - AGENTS.md:本 PR 删除了 "Pin qodercli / qoderclicn hooks in worker/src/compat.mjs; fail loudly on mismatch" 这条规则并改写了架构说明。在 worker 仍然存在的情况下请先恢复原文,架构说明的更新请单独提出讨论,由维护者确认后再改。
- 测试:
qauth包目前没有任何单元测试。请至少覆盖签名与加解密、PAT 换 jobToken、刷新、区域选择和错误分类等核心路径,可以用 httptest 模拟上游。 - 另外,worker/NOTICE 新增段落引用的
docs/capture-notes.md (local-only)不在仓库内,建议去掉这个引用或改成仓库内可访问的说明。
建议的拆分顺序:先合 PAT bridge 本体(含 qauth、许可证说明和测试,不含桌面 helper),再合 TTFB/watchdog,桌面指纹视讨论结果决定。辛苦了,有任何问题欢迎在这里讨论!
030d0cb to
4fb6d25
Compare
|
@caigee-cmd 感谢详细 review!已逐条处理完毕:
|
caigee-cmd
left a comment
There was a problem hiding this comment.
Thanks for the follow-ups — most of the earlier review items look good (TTFB/watchdog split to #315, risk.go removed, AGENTS.md untouched, qauth tests added, rebase done).
Still need a few small fixes before merge:
login/patfallback is too broad (internal/control/accounts.go). Any*OperationErrorfromLoginPATcurrently falls through toworkerAdmin, includinginvalid_credentialandcredential_save_failed. That swallows real errors and forwards the PAT to the worker. Please fall back only onprovider_unsupported; return other errors as-is.- Attribution for check-in.
checkin.gomirrors upstreamauth/checkin.go(same function names/structure), butqauth/NOTICEand theqauth.goheader only citeauth/auth.go. Please citeauth/checkin.goas well (and ideally include the MIT disclaimer paragraph). docs/ARCHITECTURE_SUMMARY.md. This PR rewrites the Qoder architecture section, while an earlier commit message said the architecture rewrite would be a separate PR. Please either restore the doc here and open a follow-up, or keep it and call that out clearly in the PR description so we can accept it on purpose.
Also please rebase onto latest main (it now includes #309 and #311).
7225a2e to
fcb62c0
Compare
|
@caigee-cmd 感谢复查,三点都处理了(commit fcb62c0),并已 rebase 到最新 main(含 #309/#311):
|
|
上次提的几点都改好了,本地测试和 CI 都通过,感谢! #315 刚合进 main,和这个 PR 有两处小冲突,麻烦 rebase 一下:
CI 重新跑过后我就合。 |
…gerprint check-in
Migrate Qoder from the per-account Node+WASM worker to a fully in-process
Bridge (PAT -> jobToken, refresh, catalog, quota, chat signing), ported from
the qoder2api reference via the new internal/providers/qoder/qauth package.
The worker path is kept only as a legacy fallback for accounts still holding a
qoder-native-v1 CLI blob.
- qauth: port cosy wire protocol (RSA+AES+custom base64+MD5), jobToken
exchange/refresh, /user/status, /model/list, OpenAPI quota, SSE reader,
busy/auth/gateway error taxonomy.
- direct: populate chat_context (text/extra.modelConfig.is_reasoning/
originalContent) and align source=1, version="3", session_type="qodercli"
so the gateway emits the reasoning_content stream again.
- adapter: parse raw gateway /model/list entries (key + display_name) into
ModelInfo so PAT accounts resolve a catalog instead of "unknown".
- catalog/probe: include in-process Qoder accounts in catalog merge and fetch
their models when the adapter has no Prober.
- checkin: present the genuine desktop device fingerprint read from the
installed app's umid/runtime-info helper (risk.go) instead of only the
PAT-derived identity, and use the OpenAPI bearer on the global region. The
campaign service only exposes the claimable daily-credit activity to the
official fingerprint; helper-missing falls back to the derived identity.
Verified live: CN check-in now sees the credit campaign ("今日已签到"),
global no longer 401s, and qwen3.8-flash streams reasoning.
One bilingual fragment per PR, per changelog/unreleased/README.md.
The in-process Bridge.QuotaSnapshot projected only UserQuota into the store headline, leaving AddOnQuota / OrgResourcePackage as detail-only fields. The worker path (quota.go snapshot) already sums the three buckets (issue caigee-cmd#229), so PAT-backed accounts drifted from the official client once the plan bucket emptied: a plan 0/0 account with a 1499/3000 add-on balance displayed 0/0 in the console. Mirror the worker-path aggregation and the Exceeded override (an available add-on keeps Exceeded false), with regression tests.
…d per review Per review on the PAT bridge PR: - Remove risk.go: executing the desktop umid/runtime-info binary server-side and sending real hardware fingerprints upstream is a security and account-linkage risk; multi-account setups on one host would share one fingerprint. Check-in now always uses the PAT-derived identity. - Restore the AGENTS.md qodercli pinning rule and the original architecture paragraph; the architecture rewrite will be proposed separately. - Trim the consolidated changelog fragment accordingly (fingerprint bullets removed; TTFB/watchdog bullets moved to the split-out PR).
Add internal/providers/qoder/qauth/NOTICE with the upstream repository URL, the ported commit (65a5fff), the copyright line, and the MIT license text, following the existing internal/providers/devin/NOTICE convention. Update the qauth.go package header and qoder2api mentions across code comments, the changelog fragment, and docs/ARCHITECTURE_SUMMARY.md to name the upstream project explicitly.
…d error taxonomy Add qauth_test.go with 27 test functions: custom base64 round-trip, MD5 signing, AES-CBC/RSA primitives, region selection and URL builders, PAT->jobToken exchange and refresh against httptest servers (success, busy 10605, 401 auth error), busy/auth/gateway error classification, error-body redaction of sensitive keys, in-stream error detection, and the SSE line reader (happy path, bare [DONE], in-stream busy, truncated stream).
…resh TestModelsAPICachesCatalogForFiveMinutes asserted absolute catalog hit counts, but the in-process boot RefreshAll now gives prober-less adapters a one-shot model discovery pass, which can land mid-test on slow CI runners (observed as hits=3 where 2 was expected). Wait for the hit counter to quiesce after setup and assert relative deltas from that baseline. Also gofmt catalog_source.go, bridge_quota_test.go, and qauth_test.go.
- login/pat: only fall back to the legacy worker path on provider_unsupported. Any other OperationError (invalid_credential, credential_save_failed) is a real failure and is returned as-is instead of being swallowed and forwarded to the worker with the PAT. Added tests for both paths. - qauth NOTICE and package header now cite auth/checkin.go alongside auth/auth.go for the in-process check-in flow, and include the full MIT disclaimer paragraph. - Restore docs/ARCHITECTURE_SUMMARY.md to main: the architecture rewrite was promised as a separate follow-up, so it should not ride in this PR.
fcb62c0 to
a2991dd
Compare
caigee-cmd
left a comment
There was a problem hiding this comment.
维护者已在 #315 合并后将本分支 rebase 到最新 main,按此前讨论解决了 adapter.go(bridges + firstByteTimeout)与 direct.go(bridgeOf + ttfb)两处冲突;本地 go test ./... 及 qoder/runtime/control -race 均通过,CI 6 项全绿。LGTM,合并。
Summary
Qoder accounts can now run fully in-process from a PAT with no per-account Node+WASM worker.
qoder-pat-v1credential format and in-processBridge(internal/providers/qoder/bridge.go): PAT→jobToken exchange, proactive/forced refresh,/user/status+ OpenAPI quota,/model/listcatalog — via theqauthpackage ported from Qoder-2API-Go (see "Upstream attribution").chat_contextfill), and catalog parsing from raw/model/list(key/display_name→CanonicalModelID).Upstream attribution
internal/providers/qoder/qauthis ported from EchoPing07/Qoder-2API-Go @65a5ffff122fdbc165275a631459b9801f9e097a(auth/auth.go), licensed MIT (Copyright (c) 2026 EchoPing). MIT permits redistribution under this project's MIT license with the notice retained; seeinternal/providers/qoder/qauth/NOTICE(same convention asinternal/providers/devin/NOTICE).Review follow-ups (2026-10-19)
risk.go(executing the installed Qoder app'sumid/runtime-infobinary and sending the real hardware fingerprint upstream) is dropped. Check-in always uses the PAT-derived identity, so no third-party binary is executed server-side and accounts on one host never share a fingerprint.worker/src/compat.mjspinning rule and the original architecture paragraph are back; the architecture-doc update will be proposed separately.main(includes fix(runtime): auto-refresh stale exhausted quota and back off probing #312); the stale "Stacked on" note is removed.Tests
go build ./...,go vet ./...,go test ./...,git diff --check(cd worker && npm test)— 84 passing