Skip to content

feat(qwenwork): daily free-credit check-in for CN and Global - #376

Merged
caigee-cmd merged 1 commit into
caigee-cmd:mainfrom
yoruuuchan:feat/qwenwork-daily-credits
Oct 24, 2026
Merged

caigee-cmd merged 1 commit into
caigee-cmd:mainfrom
yoruuuchan:feat/qwenwork-daily-credits

Conversation

@yoruuuchan

Copy link
Copy Markdown
Contributor

Summary

Adds QwenWork (千问办公) CN and Global to the shared check-in framework: account-card manual check-in, off-by-default automatic check-in, history, and the existing provider-level/account-level schedule settings. No new page, no provider-specific console code.

The provider's Checkin first calls the desktop client's growth-card claim API, then falls back to confirming the server-granted daily credits when that route is absent.

What the upstream actually exposes

Facts gathered from the installed desktop bundles, the app's config-service log, and live calls with real accounts:

Fact Evidence
The growth card calls GET /sash/api/v1/me/daily-check-in/status and POST /sash/api/v1/me/daily-check-in/claim out/main/main.js in both bundles (global 1.0.4, CN 1.4.0): DAILY_CHECK_IN_STATUS_PATH, DAILY_CHECK_IN_CLAIM_PATH, statuses CLAIMABLE/CLAIMED_TODAY/DISABLED/NOT_STARTED/ENDED, results CLAIMED/ALREADY_CLAIMED
The card is gated by remote config operations/announcement:credits-growth-card same bundle: checkinEnabled, IPC operation:credits-growth-card:claim-checkin
That config is currently empty for both regions app logs: Dispatch null on initial sync for opt-in registration with no remote value {"namespace":"operations","key":"announcement:credits-growth-card"}
Both production gateways answer 404 for every /sash path live probes on gateway.qwenwork.ai and gateway.qwenwork.cn with (a) a valid device bearer, (b) a garbage bearer, (c) a full COSY-signed request: all 404, empty body
CN free credits are granted server-side at 00:00 Asia/Shanghai GET /api/v1/adapter/user/wallets → daily_credits.total_balance = 100, wallet valid_to = 2026-10-25T00:00:00+08:00; CN client copy: 今日已获得 {{credits}} 免费积分 / 每日 0 点刷新
Global free credits are a daily login bonus, with no per-day endpoint qwenwork.ai/pricing: Free plan “200 daily login bonus credits”; GET /api/v1/adapter/user/wallets → 404 on the global gateway; account-context returns only quota.remaining (700 = 500 signup + 200 daily on the test account)

So today there is no claimable campaign in either region: the claim route is not deployed, and the credits are issued by the server. The implementation reports what the API can actually prove instead of inventing a success.

Behaviour

Upstream state Result
Status CLAIMABLE, claim returns CLAIMED success with +N 积分 reward
Claim returns ALREADY_CLAIMED already
Status CLAIMED_TODAY already, with streak/reward when reported
Status DISABLED / NOT_STARTED / ENDED skipped with the matching reason
Status/claim route 404/405/501 (current production) falls back to the daily-grant probe
CN wallet daily balance > 0 already + 每日免费积分已到账 +N(每日 0 点刷新) and the reward amount
CN wallet daily balance 0 skipped + 今日每日免费积分尚未到账(每日 0 点刷新) (a spent balance and an unissued balance cannot be told apart)
Global fallback skipped + 签到接口未开放(上游 404);每日登录奖励由服务端自动发放,当前剩余额度 N
401/403 from status, claim, or wallet error (authentication failed), so the account surfaces as failed rather than claimed
Claim/status/wallet 5xx, bad JSON, unexpected result error

The per-account checkinRunning guard, RecordCheckin, local-day short-circuit, and quota refresh are the existing runtime paths, unchanged.

Files

  • internal/providers/qwenwork/checkin.go — claim flow, status mapping, CN wallet fallback, global quota fallback, desktop growth-card headers.
  • internal/providers/qwenwork/credential.go, client.go — Region on the site record, Checkin on the adapter.
  • internal/providers/registry.go — CheckinPolicy (Asia/Shanghai) on both QwenWork regions.
  • internal/providers/qwenwork/checkin_test.go, registry_test.go, client_test.go — new coverage and the updated adapter-capability assertion.
  • README.md, README_EN.md, changelog/unreleased/qwenwork-daily-checkin.md — user-facing notes.

No frontend change, so internal/webui/static is untouched and npm run sync is not needed.

Tests

CI-equivalent run on Linux (golang:1.25 container, mounted checkout):

go vet ./...                 # pass
go test ./...                # pass
go test -race ./...          # pass
python scripts/release-notes.py validate   # pass

New unit tests cover: claim success, CLAIMED_TODAY with and without reward, ALREADY_CLAIMED, the three closed campaign states, CN wallet grant, CN zero balance, global closed-campaign message, authentication failure on status and wallet, claim HTTP error, unexpected claim result, and the registry policy.

On Windows the same suite still reports the failures that upstream main already has on that host (internal/api, internal/executor, internal/providers/qoder, internal/runtime, internal/store); I reproduced the identical list on a clean origin/main worktree, and internal/providers/qwenwork passes there.

Live verification

Isolated instance (separate build, QODER_DATA_DIR, PORT, read-only copy of the live database trimmed to the two QwenWork accounts). The production container, its volume, and its accounts were not modified.

Manual check-in on 2026-10-24 00:15 +08:00, and again through the scheduler at 00:15 with auto_checkin=1, checkin_time=00:01:

  • CN account — already, 每日免费积分已到账 +100(每日 0 点刷新); wallet still reports daily_credits = 100 expiring at the next 00:00.
  • Global account — skipped, 签到接口未开放(上游 404);每日登录奖励由服务端自动发放,当前剩余额度 700.
  • Both paths wrote checkin_records rows and refreshed the stored quota (fetched_at moved with the check-in).

Known limitation

The Global daily 200 cannot be confirmed per day through any endpoint I could find: the claim route is not routed and /api/v1/adapter/user/wallets exists only on CN. The global path therefore records a skip with the reason and the current quota rather than claiming a grant it cannot see. If the campaign is enabled later, the claim branch already implements the desktop protocol and needs no change.

No credentials, tokens, host IPs, or account identifiers are included in the diff, tests, or logs above.

Register QwenWork CN and Global in the shared check-in framework and implement
the provider's Checkin: try the desktop growth-card claim API first
(/sash/api/v1/me/daily-check-in/status + /claim), then confirm the server-side
daily grant when the gateway does not route that prefix.

CN reads /api/v1/adapter/user/wallets and reports the granted daily credits
(00:00 Asia/Shanghai refresh). Global has no per-day wallet endpoint, so it
reports the claim-route gap and the account-context quota instead of a fake
success. Manual and scheduled check-ins share the existing per-account and
provider-time settings.

@caigee-cmd caigee-cmd left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

审核结论:建议合(CI 全绿),带两点备注

架构正确:接入现有 Checkin / CheckinPolicy,无新页面;claim 优先、生产 /sash 404 再走钱包/额度兜底,不伪造成功。测试覆盖和 live 说明都够用。

备注(非阻塞)

  1. CN 钱包余额为 0 → skipped:skipped 不是 error,当天不会再进调度(含 21:00 重试)。若自动签到时间偏早、日额度尚未到账,会整日卡住。现状可接受(与「花光 vs 未到账」不可分有关),建议用户侧默认时间偏后,或后续再考虑「尚未到账」允许同日重试。
  2. CN already 的 RewardCredits:填的是钱包日额度剩余,不是「本次领取量」;控制台若不展示该字段则无感。

Global 长期只能 skipped + 原因文案,符合当前上游;每天记一条 skip 即可,不会刷爆。

未发现安全/密钥泄露问题。未 merge,等维护者点头。

@caigee-cmd
caigee-cmd merged commit 6aaffd6 into caigee-cmd:main Oct 24, 2026
6 checks passed
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.

2 participants