mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
fix(account): 保留未校验的通知元数据
This commit is contained in:
1 parent
6ac5c103db
commit
1f312b6282
14 files changed
+50
-29
No files matched your search
@@ -41,8 +41,8 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `cordis/request-run-resolved` | `emit` | [`packages/extensions/cordis-host-runner/src/types.ts:377`](../packages/extensions/cordis-host-runner/src/types.ts) | [`cordis-host-runner`](../packages/extensions/cordis-host-runner) (`emit`) | `remotes` |
|
||||
| `credentials/record-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:99`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization), [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform), `remotes` |
|
||||
| `credentials/reference-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:87`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:91`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:87`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:97`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:93`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/signed-out` | `emit` | [`packages/credentials/deepseek-account/src/index.ts:12`](../packages/credentials/deepseek-account/src/index.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | [`deepseek-account`](../packages/credentials/deepseek-account) |
|
||||
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `workspace-controller` |
|
||||
| `feedback/committed` | `parallel` | [`packages/feedback/message-feedback/src/index.ts:58`](../packages/feedback/message-feedback/src/index.ts) | [`message-feedback`](../packages/feedback/message-feedback) (`parallel`) | [`session-telemetry-otel`](../packages/session/session-telemetry-otel) |
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
| `cordis/request-run-resolved` | `emit` | [`packages/extensions/cordis-host-runner/src/types.ts:377`](../packages/extensions/cordis-host-runner/src/types.ts) | [`cordis-host-runner`](../packages/extensions/cordis-host-runner) (`emit`) | `remotes` |
|
||||
| `credentials/record-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:99`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization), [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform), `remotes` |
|
||||
| `credentials/reference-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:87`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:91`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:87`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:97`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:93`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/signed-out` | `emit` | [`packages/credentials/deepseek-account/src/index.ts:12`](../packages/credentials/deepseek-account/src/index.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | [`deepseek-account`](../packages/credentials/deepseek-account) |
|
||||
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `workspace-controller` |
|
||||
| `feedback/committed` | `parallel` | [`packages/feedback/message-feedback/src/index.ts:58`](../packages/feedback/message-feedback/src/index.ts) | [`message-feedback`](../packages/feedback/message-feedback) (`parallel`) | [`session-telemetry-otel`](../packages/session/session-telemetry-otel) |
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
# After editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-alpha.4/account-notification-fields/guide.md
|
||||
/:
|
||||
en: 5121efbea911b60c
|
||||
zh: 5fceabd7a9de1627
|
||||
en: 9b6666d42852a11b
|
||||
zh: b14c7d8590c54ba5
|
||||
/update-account-notification-consumers:
|
||||
en: 586faed9ab20343f
|
||||
zh: fb3cc099b39b0386
|
||||
/update-account-notification-consumers/change:
|
||||
en: 66a0d330922e4794
|
||||
zh: ebf07a21bb01e64c
|
||||
en: 20cc8ba42b771270
|
||||
zh: da0ca5f650c74117
|
||||
/update-account-notification-consumers/migration:
|
||||
en: c177a8cfccf3a2e1
|
||||
zh: 4529b8b553c3eaef
|
||||
en: e9fe0c1ebba8acfc
|
||||
zh: 05b94685fb4c5ead
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
kind: upgrade-guide
|
||||
description: "AccountBonusNotification removes unused bonus fields and permits notices without an expiry."
|
||||
description: "AccountBonusNotification exposes unvalidated optional metadata and permits notices without an expiry."
|
||||
---
|
||||
|
||||
# Update account notification consumers
|
||||
@@ -9,10 +9,10 @@ English | [中文](guide.zh.md)
|
||||
|
||||
## Change
|
||||
|
||||
The public `AccountBonusNotification` returned by `DeepSeekAccount.getUnnotifiedBonuses()` and `account/getUnnotifiedBonuses` no longer includes `campaign`, `amount`, `currency`, or `grantedAt`. Notifications retain `orderId`, `message`, and `expiresAt`, and add an optional `title`. An empty `expiresAt` means the notification never expires. `orderId` accepts arbitrary strings rather than requiring UUIDs.
|
||||
The public `AccountBonusNotification` returned by `DeepSeekAccount.getUnnotifiedBonuses()` and `account/getUnnotifiedBonuses` preserves `campaign`, `amount`, `currency`, and `grantedAt` as optional, unvalidated metadata typed as `JsonValue`. Notifications retain `orderId`, `message`, and `expiresAt`, and add an optional `title`. An empty `expiresAt` means the notification never expires. `orderId` accepts arbitrary strings rather than requiring UUIDs.
|
||||
|
||||
## Migration
|
||||
|
||||
1. Remove reads of the deleted fields from account notification consumers. Display `message` and use the client's default title when `title` is absent.
|
||||
1. Narrow the optional metadata values before using them; their presence and format are no longer guaranteed. Display `message` and use the client's default title when `title` is absent.
|
||||
2. Treat an empty `expiresAt` as no expiry before parsing timestamps. Keep `orderId` unchanged when acknowledging a notification.
|
||||
3. Update provider fixtures to use the current fields. Confirm that a notification with a non-UUID ID and empty expiry displays and can be acknowledged.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
kind: upgrade-guide
|
||||
description: "AccountBonusNotification 移除未使用的赠金字段,并允许通知永不过期。"
|
||||
description: "AccountBonusNotification 提供未经校验的可选元数据,并允许通知永不过期。"
|
||||
---
|
||||
|
||||
# 更新账号通知使用方
|
||||
@@ -9,10 +9,10 @@ description: "AccountBonusNotification 移除未使用的赠金字段,并允
|
||||
|
||||
## 变更
|
||||
|
||||
`DeepSeekAccount.getUnnotifiedBonuses()` 和 `account/getUnnotifiedBonuses` 返回的公开类型 `AccountBonusNotification` 不再包含 `campaign`、`amount`、`currency` 或 `grantedAt`。通知保留 `orderId`、`message` 和 `expiresAt`,并新增可选的 `title`。空字符串 `expiresAt` 表示通知永不过期。`orderId` 接受任意字符串,不再要求 UUID 格式。
|
||||
`DeepSeekAccount.getUnnotifiedBonuses()` 和 `account/getUnnotifiedBonuses` 返回的公开类型 `AccountBonusNotification` 保留 `campaign`、`amount`、`currency` 和 `grantedAt`,作为类型为 `JsonValue` 的可选元数据,不做校验。通知保留 `orderId`、`message` 和 `expiresAt`,并新增可选的 `title`。空字符串 `expiresAt` 表示通知永不过期。`orderId` 接受任意字符串,不再要求 UUID 格式。
|
||||
|
||||
## 迁移
|
||||
|
||||
1. 移除账号通知使用方对已删除字段的读取。展示 `message`,在 `title` 缺省时使用客户端默认标题。
|
||||
1. 使用可选元数据前先收窄类型;这些值不再保证存在或符合原有格式。展示 `message`,在 `title` 缺省时使用客户端默认标题。
|
||||
2. 解析时间戳前,将空字符串 `expiresAt` 视为永不过期。确认通知时原样传递 `orderId`。
|
||||
3. 更新提供者测试夹具以使用当前字段。确认非 UUID 标识、空过期时间的通知可以展示并确认。
|
||||
@@ -15,8 +15,8 @@
|
||||
en: af856ba79fe31b8e
|
||||
zh: 15b7d1a5d1856de2
|
||||
/deepseek-ai-dsh-deepseek-account-platform/use-this-package:
|
||||
en: b64ce39acb777c13
|
||||
zh: c5f138c695be73d1
|
||||
en: 56bee240f50c293a
|
||||
zh: 6c4c5de6088c9d79
|
||||
/deepseek-ai-dsh-deepseek-account-platform/understand-the-implementation:
|
||||
en: 76d2da2dab100ac3
|
||||
zh: 2c9404f27915daab
|
||||
|
||||
@@ -38,7 +38,7 @@ Token resolution refuses requests while local sign-out is in progress. Successfu
|
||||
|
||||
getProfile / getBalance sends the stored grant in the x-dsh-auth-token header to GET /auth-api/v0/users/current and GET /api/v0/users/get_user_summary on platformOrigin. The grant issuer must match that origin. Host projects only the account UID, profile name, avatar URL, phone or email exactly as masked by Platform, and normal_wallets / bonus_wallets currency/balance strings; response tokens and other fields are discarded. A balance or bonus-amount string is accepted when it matches the numeric grammar Platform's Web client already passes to big.js, which allows an omitted integer or fraction part and a decimal exponent, so values such as 0E-16 and 5.0000000000000000 stay valid; the original string is retained and NaN, Infinity and malformed text are rejected. Bonus wallets remain separate from recharge balances. Credential changes and disposal invalidate in-flight queries.
|
||||
|
||||
getUnnotifiedBonuses reads GET /api/v0/users/get_unnotified_bonuses and ackBonusNotified posts POST /api/v0/users/ack_bonus_notified with a JSON body naming the order on the same origin, each sending the five client headers built from the caller's metadata. Both resolve the account identity for the captured grant first, so a signed-out or switched account yields null or false instead of acknowledging another account's bonus, and a read publishes only after the whole query settled under one credential lifetime. The Host forwards the bonus list in Platform order, retains the string fields order_id, expires_at and msg, and maps them to orderId, expiresAt and message. An optional string title is forwarded unchanged; null or absent titles use the client default. An empty, null or absent expires_at becomes an empty expiresAt and means the notice never expires. Order IDs need not be UUIDs; campaign, amount, currency and granted_at are ignored and may be absent; malformed payloads, other HTTP failures and other business failures throw, while a credential rejection (HTTP 401 or response code `40003`) invalidates the current grant and yields null or false.
|
||||
getUnnotifiedBonuses reads GET /api/v0/users/get_unnotified_bonuses and ackBonusNotified posts POST /api/v0/users/ack_bonus_notified with a JSON body naming the order on the same origin, each sending the five client headers built from the caller's metadata. Both resolve the account identity for the captured grant first, so a signed-out or switched account yields null or false instead of acknowledging another account's bonus, and a read publishes only after the whole query settled under one credential lifetime. The Host forwards the bonus list in Platform order, retains the string fields order_id, expires_at and msg, and maps them to orderId, expiresAt and message. An optional string title is forwarded unchanged; null or absent titles use the client default. An empty, null or absent expires_at becomes an empty expiresAt and means the notice never expires. Order IDs need not be UUIDs; campaign, amount, currency and granted_at are optional, unvalidated metadata forwarded as campaign, amount, currency and grantedAt; malformed payloads, other HTTP failures and other business failures throw, while a credential rejection (HTTP 401 or response code `40003`) invalidates the current grant and yields null or false.
|
||||
|
||||
Balance requests use balanceTimeoutMs (30,000ms by default); timeout returns a failed outcome without clearing the account or manufacturing a zero balance. Configure platformOrigin, allowLoopbackHttp, requestTimeoutMs, balanceTimeoutMs, and attemptTimeoutMs in the plugin row. HTTP is accepted only for explicitly enabled loopback development. The provider registers /oauth/callback on the existing Host webServer before auth_init, validates state, exchanges an S256 PKCE code once, and commits a grant before redirecting to auth_exchange.biz_data.authorized_url. Browser destinations default to the configured platform origin and always require the fixed /dsh/authorize or /dsh/authorized path. The completion URL sets `login_source` to the initiating client (`web` or `desktop`) and preserves other Platform-supplied query parameters. Device identity is a separate random UUID record shared by processes using the same credential store; device_model reports OS and architecture.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ getPlatformSession 仅在已存授权的 issuer 与 platformOrigin 一致时导
|
||||
|
||||
getProfile / getBalance 将保存的授权 token 通过 x-dsh-auth-token 请求头,向 platformOrigin 上的 GET /auth-api/v0/users/current 和 GET /api/v0/users/get_user_summary 发起请求。授权签发来源必须与该来源一致。Host 只投影账号 UID、资料名称、头像 URL、由 Platform 脱敏的手机号或邮箱(原样保留),以及 normal_wallets / bonus_wallets 的币种和余额字符串,丢弃响应 token 与其他字段。余额和赠金金额字符串只要符合 Platform Web 客户端交给 big.js 的数字文法即可通过,该文法和 big.js 一致,允许省略整数或小数部分以及十进制指数,因此 0E-16、5.0000000000000000 这类值仍然有效;原始字符串会保留,NaN、Infinity 和非法文本仍被拒绝。赠送钱包不计入充值余额。凭证变化和销毁会使进行中的查询失效。
|
||||
|
||||
getUnnotifiedBonuses 读取同一来源上的 GET /api/v0/users/get_unnotified_bonuses,ackBonusNotified 向 POST /api/v0/users/ack_bonus_notified 发送仅含订单号的 JSON 正文,两者都按调用方元数据组装这五个客户端请求头。二者都先为捕获到的授权解析账号身份,因此退登或切号时返回 null 或 false,而不会确认另一个账号的赠金;一次读取只有在同一凭证生命周期内全部结算后才发布。Host 按 Platform 返回顺序转发赠金列表,保留字符串字段 order_id、expires_at 和 msg,并映射为 orderId、expiresAt 和 message。可选的字符串 title 原样转发;null 或缺省表示使用客户端默认标题。expires_at 为空字符串、null 或缺省时,统一转为空字符串 expiresAt,表示通知永不过期。订单号不要求 UUID 格式;campaign、amount、currency 和 granted_at 会被忽略,也可以缺省;格式错误、其他 HTTP 失败和其他业务失败都会抛出,而凭据被拒绝(HTTP 401 或响应码 `40003`)会使当前授权失效并返回 null 或 false。
|
||||
getUnnotifiedBonuses 读取同一来源上的 GET /api/v0/users/get_unnotified_bonuses,ackBonusNotified 向 POST /api/v0/users/ack_bonus_notified 发送仅含订单号的 JSON 正文,两者都按调用方元数据组装这五个客户端请求头。二者都先为捕获到的授权解析账号身份,因此退登或切号时返回 null 或 false,而不会确认另一个账号的赠金;一次读取只有在同一凭证生命周期内全部结算后才发布。Host 按 Platform 返回顺序转发赠金列表,保留字符串字段 order_id、expires_at 和 msg,并映射为 orderId、expiresAt 和 message。可选的字符串 title 原样转发;null 或缺省表示使用客户端默认标题。expires_at 为空字符串、null 或缺省时,统一转为空字符串 expiresAt,表示通知永不过期。订单号不要求 UUID 格式;campaign、amount、currency 和 granted_at 均为可选元数据,不做校验,分别原样转发为 campaign、amount、currency 和 grantedAt;格式错误、其他 HTTP 失败和其他业务失败都会抛出,而凭据被拒绝(HTTP 401 或响应码 `40003`)会使当前授权失效并返回 null 或 false。
|
||||
|
||||
余额请求使用 balanceTimeoutMs(默认 30,000ms);超时返回失败结果,不清除账号,也不制造零余额。在插件行配置 platformOrigin、allowLoopbackHttp、requestTimeoutMs、balanceTimeoutMs 和 attemptTimeoutMs。HTTP 仅用于显式启用的本机开发。提供者先在现有 Host webServer 注册 /oauth/callback,再调用 auth_init;校验 state、使用 S256 PKCE 授权码兑换一次,并在跳转 auth_exchange.biz_data.authorized_url 前提交授权记录。浏览器地址默认要求匹配配置的平台来源,并始终要求固定的 /dsh/authorize 或 /dsh/authorized 路径。完成页地址将 `login_source` 设为发起登录的客户端类型(`web` 或 `desktop`),并保留平台返回的其他查询参数。设备标识是独立的随机 UUID 记录,由使用同一凭证存储的进程共享;device_model 报告操作系统和架构。
|
||||
|
||||
|
||||
@@ -15,7 +15,10 @@ const wallet = z.object({
|
||||
currency: z.enum(['CNY', 'USD']), balance: z.string().regex(decimal),
|
||||
})
|
||||
const summary = z.object({ normal_wallets: z.array(wallet), bonus_wallets: z.array(wallet) })
|
||||
// Protocol responses are JSON-decoded; metadata keeps any JSON value without field validation.
|
||||
const bonusMetadata = z.custom<Exclude<AccountBonusNotification['campaign'], undefined>>().optional()
|
||||
const bonus = z.object({
|
||||
campaign: bonusMetadata, amount: bonusMetadata, currency: bonusMetadata, granted_at: bonusMetadata,
|
||||
order_id: z.string(), title: z.string().nullish().transform(value => value ?? undefined), expires_at: z.string().nullish().transform(value => value ?? ''), msg: z.string(),
|
||||
})
|
||||
// The shared response reader already unwraps biz_data, so the payload is the bonus list itself.
|
||||
@@ -96,6 +99,10 @@ export async function readUnnotifiedBonuses(origin: string, token: string,
|
||||
signal: AbortSignal, headers: Record<string, string>): Promise<readonly AccountBonusNotification[]> {
|
||||
const parsed = accountPayload(unnotified, await requestUnnotifiedBonuses(origin, token, signal, headers), 'bonus')
|
||||
return parsed.map(row => ({
|
||||
...(row.campaign === undefined ? {} : { campaign: row.campaign }),
|
||||
...(row.amount === undefined ? {} : { amount: row.amount }),
|
||||
...(row.currency === undefined ? {} : { currency: row.currency }),
|
||||
...(row.granted_at === undefined ? {} : { grantedAt: row.granted_at }),
|
||||
orderId: row.order_id as AccountBonusOrderId, expiresAt: row.expires_at, message: row.msg,
|
||||
...(row.title === undefined ? {} : { title: row.title }),
|
||||
}))
|
||||
|
||||
@@ -192,8 +192,10 @@ it('reads unnotified bonuses with the platform origin, grant header, and locale
|
||||
expect(batch).toEqual<AccountBonusBatch>({
|
||||
accountId: USER as AccountUserId,
|
||||
bonuses: [
|
||||
{ orderId: ORDER as AccountBonusOrderId, expiresAt: '2026-10-21T12:00:00Z', message: '已赠送您 5.00 元 DSH 体验赠金。' },
|
||||
{ orderId: SECOND_ORDER as AccountBonusOrderId, expiresAt: '2026-10-20T12:00:00Z', message: '已赠送您 1.50 元 DSH 体验赠金。' },
|
||||
{ orderId: ORDER as AccountBonusOrderId, campaign: 'dsh_login_bonus', amount: '5.00', currency: 'CNY',
|
||||
grantedAt: '2026-09-21T12:00:00Z', expiresAt: '2026-10-21T12:00:00Z', message: '已赠送您 5.00 元 DSH 体验赠金。' },
|
||||
{ orderId: SECOND_ORDER as AccountBonusOrderId, campaign: 'dsh_login_bonus', amount: '1.50', currency: 'CNY',
|
||||
grantedAt: '2026-09-20T12:00:00Z', expiresAt: '2026-10-20T12:00:00Z', message: '已赠送您 1.50 元 DSH 体验赠金。' },
|
||||
],
|
||||
})
|
||||
expect(f.requests).toEqual([
|
||||
@@ -205,15 +207,16 @@ it('reads unnotified bonuses with the platform origin, grant header, and locale
|
||||
})
|
||||
|
||||
it.each([
|
||||
['absent', {}],
|
||||
['unvalidated', { campaign: null, amount: 'not-a-number', currency: 'EUR', granted_at: 42 }],
|
||||
])('accepts opaque order IDs with %s unused fields and acknowledges the same ID', async (_name, extra) => {
|
||||
['absent', {}, {}],
|
||||
['unvalidated', { campaign: null, amount: 'not-a-number', currency: 'EUR', granted_at: 42 },
|
||||
{ campaign: null, amount: 'not-a-number', currency: 'EUR', grantedAt: 42 }],
|
||||
])('accepts opaque order IDs with %s unused fields and acknowledges the same ID', async (_name, extra, expected) => {
|
||||
const f = await fixture()
|
||||
await f.grant('test-account-token')
|
||||
f.bonuses([{ order_id: 'model-update-1', expires_at: '2099-01-01T00:00:00Z', title: 'Model news', msg: 'Model updated', ...extra }])
|
||||
const batch = await f.account.getUnnotifiedBonuses(clientMetadata('en'))
|
||||
expect(batch?.bonuses).toEqual([
|
||||
{ orderId: 'model-update-1', expiresAt: '2099-01-01T00:00:00Z', title: 'Model news', message: 'Model updated' },
|
||||
{ orderId: 'model-update-1', expiresAt: '2099-01-01T00:00:00Z', title: 'Model news', message: 'Model updated', ...expected },
|
||||
])
|
||||
const notice = batch!.bonuses[0]!
|
||||
expect(await f.account.ackBonusNotified(batch!.accountId, notice.orderId, clientMetadata('en'))).toBe(true)
|
||||
|
||||
@@ -35,13 +35,15 @@
|
||||
"@deepseek-ai/cordis": "workspace:~",
|
||||
"@deepseek-ai/dsh-brand": "workspace:*",
|
||||
"@deepseek-ai/dsh-agent": "workspace:*",
|
||||
"@deepseek-ai/dsh-llm": "workspace:*"
|
||||
"@deepseek-ai/dsh-llm": "workspace:*",
|
||||
"@deepseek-ai/dsh-util-values": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/cordis": "workspace:~",
|
||||
"@deepseek-ai/dsh-brand": "workspace:*",
|
||||
"@deepseek-ai/dsh-agent": "workspace:*",
|
||||
"@deepseek-ai/dsh-llm": "workspace:*"
|
||||
"@deepseek-ai/dsh-llm": "workspace:*",
|
||||
"@deepseek-ai/dsh-util-values": "workspace:*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@deepseek-ai/dsh-agent": {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** Client-supplied request identity and client-safe account state; credentials never cross this projection. */
|
||||
import type {} from '@deepseek-ai/cordis'
|
||||
import type { Branded } from '@deepseek-ai/dsh-brand'
|
||||
import type { JsonValue } from '@deepseek-ai/dsh-util-values'
|
||||
|
||||
/** Identity of the requesting UI for one account operation; the Host derives Platform request headers from it. */
|
||||
export interface AccountClientMetadata {
|
||||
@@ -68,6 +69,11 @@ export interface AccountBonusNotification {
|
||||
/** Server-localized plain-text title; absent responses use the localized bonus title. */
|
||||
readonly title?: string
|
||||
readonly orderId: AccountBonusOrderId
|
||||
/** Optional Platform metadata, forwarded without validation. */
|
||||
readonly campaign?: JsonValue
|
||||
readonly amount?: JsonValue
|
||||
readonly currency?: JsonValue
|
||||
readonly grantedAt?: JsonValue
|
||||
/** Platform expiry timestamp; an empty string means the notice never expires. */
|
||||
readonly expiresAt: string
|
||||
/** Server-localized plain text ready for display. */
|
||||
|
||||
@@ -4663,7 +4663,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
|
||||
},
|
||||
{
|
||||
name: 'AccountBonusNotification',
|
||||
declaration: 'export interface AccountBonusNotification {\n readonly title?: string;\n readonly orderId: AccountBonusOrderId;\n readonly expiresAt: string;\n readonly message: string;\n}',
|
||||
declaration: 'export interface AccountBonusNotification {\n readonly title?: string;\n readonly orderId: AccountBonusOrderId;\n readonly campaign?: JsonValue;\n readonly amount?: JsonValue;\n readonly currency?: JsonValue;\n readonly grantedAt?: JsonValue;\n readonly expiresAt: string;\n readonly message: string;\n}',
|
||||
},
|
||||
{
|
||||
name: 'AccountBonusOrderId',
|
||||
|
||||
Generated
+3
@@ -7357,6 +7357,9 @@ importers:
|
||||
'@deepseek-ai/dsh-llm':
|
||||
specifier: workspace:*
|
||||
version: link:../../llm/llm
|
||||
'@deepseek-ai/dsh-util-values':
|
||||
specifier: workspace:*
|
||||
version: link:../../util/values
|
||||
|
||||
packages/credentials/deepseek-account-platform:
|
||||
dependencies:
|
||||
|
||||
Reference in new issue
Block a user