dsh-subscriptions 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/lib/auth/device-flow.js +6 -3
- package/lib/auth/oauth-flow.js +41 -8
- package/lib/auth/rpc.d.ts +3 -1
- package/lib/auth/rpc.js +10 -1
- package/lib/client/ProviderAccountManager.js +34 -41
- package/lib/client/ProviderModelEditor.js +5 -9
- package/lib/client/SpeedSelect.js +8 -7
- package/lib/client/SubscriptionUsageBadge.js +6 -5
- package/lib/client/SubscriptionsSection.d.ts +21 -73
- package/lib/client/SubscriptionsSection.js +130 -104
- package/lib/client/UsageBadgeDisplaySetting.js +4 -8
- package/lib/client/host-contract.d.ts +1 -1
- package/lib/client/host-contract.js +22 -0
- package/lib/client/locales.d.ts +58 -0
- package/lib/client/locales.js +58 -0
- package/lib/client/provider-settings-styles.d.ts +3 -0
- package/lib/client/provider-settings-styles.js +206 -0
- package/lib/client/reset-action.d.ts +14 -0
- package/lib/client/reset-action.js +15 -0
- package/lib/client/reset-credits-view.d.ts +53 -0
- package/lib/client/reset-credits-view.js +103 -0
- package/lib/client.js +937 -310
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +9 -0
- package/lib/index.js +6058 -5298
- package/lib/model-defaults.d.ts +4 -5
- package/lib/model-defaults.js +18 -14
- package/lib/providers/account-preferences.js +3 -2
- package/lib/providers/antigravity.d.ts +0 -2
- package/lib/providers/antigravity.js +5 -9
- package/lib/providers/catalog-store.d.ts +3 -2
- package/lib/providers/catalog-store.js +57 -26
- package/lib/providers/claude.d.ts +22 -3
- package/lib/providers/claude.js +118 -20
- package/lib/providers/codex-search.js +5 -2
- package/lib/providers/codex.d.ts +15 -2
- package/lib/providers/codex.js +77 -9
- package/lib/providers/common.d.ts +38 -0
- package/lib/providers/common.js +44 -18
- package/lib/providers/copilot.d.ts +2 -1
- package/lib/providers/copilot.js +13 -6
- package/lib/providers/cursor-adapter.d.ts +35 -0
- package/lib/providers/cursor-adapter.js +245 -4
- package/lib/providers/cursor-auth.js +11 -4
- package/lib/providers/cursor-usage.js +2 -1
- package/lib/providers/external-usage.js +2 -1
- package/lib/providers/grok.d.ts +2 -2
- package/lib/providers/grok.js +16 -11
- package/lib/providers/minimax-usage.js +2 -1
- package/lib/providers/pool-health.d.ts +2 -0
- package/lib/providers/pool-health.js +9 -0
- package/lib/providers/pool-usage.d.ts +13 -1
- package/lib/providers/pool-usage.js +39 -7
- package/lib/providers/pool.d.ts +7 -5
- package/lib/providers/pool.js +89 -12
- package/lib/providers/rate-limit.d.ts +0 -14
- package/lib/providers/rate-limit.js +0 -26
- package/lib/providers/replay.d.ts +4 -0
- package/lib/providers/replay.js +50 -0
- package/lib/providers/reset-redemption.d.ts +51 -0
- package/lib/providers/reset-redemption.js +102 -0
- package/lib/tools/image-generate.js +2 -1
- package/lib/tools/video-generate.d.ts +0 -5
- package/lib/tools/video-generate.js +25 -14
- package/lib/tools/x-search.js +2 -2
- package/lib/translate/anthropic.d.ts +21 -2
- package/lib/translate/anthropic.js +35 -11
- package/lib/translate/antigravity.js +13 -6
- package/lib/translate/chat-completions.js +1 -1
- package/lib/translate/resolved.d.ts +24 -0
- package/lib/translate/resolved.js +66 -3
- package/lib/translate/responses.js +8 -6
- package/lib/translate/sse.js +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,6 +97,43 @@ in **Settings → Subscriptions**.
|
|
|
97
97
|
|
|
98
98
|

|
|
99
99
|
|
|
100
|
+
#### Codex usage limit resets
|
|
101
|
+
|
|
102
|
+
The Codex account card shows banked full-reset credits and their expirations
|
|
103
|
+
in a closed disclosure. A failed optional lookup reports an error without
|
|
104
|
+
hiding ordinary quota windows. **Use…** selects the earliest-expiring available
|
|
105
|
+
credit and requires a fresh unscoped weekly reading of at least 80%, then an
|
|
106
|
+
explicit confirmation and acknowledgment. Confirmation expires after 60
|
|
107
|
+
seconds; the server rechecks usage and credit availability before submission.
|
|
108
|
+
|
|
109
|
+
One reset consumes one credit and resets weekly and 5-hour limits. This
|
|
110
|
+
interface cannot undo it. An unconfirmed outcome blocks further redemption
|
|
111
|
+
for that account in the current host process. Restarting clears that block,
|
|
112
|
+
but must not be used to bypass it: check credits and limits in Codex before
|
|
113
|
+
retrying, because the first submission may already have spent a credit.
|
|
114
|
+
The private endpoint is covered by offline fakes, not live-account checks.
|
|
115
|
+
See the [manual reset decision](.agents/notes/implemented/provider/2026-10-04-codex-manual-reset.md)
|
|
116
|
+
for the retry boundary and verification limits.
|
|
117
|
+
|
|
118
|
+
#### Claude usage limit resets
|
|
119
|
+
|
|
120
|
+
The Claude account card shows banked limit resets from Anthropic's
|
|
121
|
+
`cedar_ember` program, in the same closed disclosure Codex uses. It lists one
|
|
122
|
+
row per grant, not one per credit, and the summary counts remaining resets by
|
|
123
|
+
summing `resetsLeft` over grants that are neither expired nor paused. Each row
|
|
124
|
+
states whether that grant is available, not yet usable, paused, exhausted, or
|
|
125
|
+
expired, with its remaining count and when it lapses. That time is the grant's
|
|
126
|
+
expiry: it is not a window reset and does not move the elapsed-time cursor.
|
|
127
|
+
|
|
128
|
+
This is **display only**. `claimable` is shown as data on a text row, and the
|
|
129
|
+
page has no control that spends a Claude reset, because the response shape is
|
|
130
|
+
not an Anthropic contract. An ineligible account, a grant-less block, or a
|
|
131
|
+
rejected optional query leaves ordinary session and weekly windows untouched
|
|
132
|
+
and shows no list; a failed lookup shows a fixed sentence rather than the
|
|
133
|
+
provider's text. No live account was used to verify what Anthropic returns. See
|
|
134
|
+
[the evidence and limits](docs/claude-banked-resets.md) and the
|
|
135
|
+
[display decision](.agents/notes/implemented/provider/2026-10-08-claude-banked-reset-display.md).
|
|
136
|
+
|
|
100
137
|
## Install
|
|
101
138
|
|
|
102
139
|
Current source is tested with DSH `0.1.7-rc.2`, `0.2.0-rc.1`, and
|
|
@@ -183,6 +220,33 @@ usage.
|
|
|
183
220
|
The plugin follows DSH network settings. Its former proxy configuration and
|
|
184
221
|
UI have been retired; an old plugin proxy config file is ignored.
|
|
185
222
|
|
|
223
|
+
## Claude prompt-cache TTL
|
|
224
|
+
|
|
225
|
+
Set `claudePromptCacheTtl: '5m'` (default) or `'1h'` in the plugin config and
|
|
226
|
+
restart DSH. This affects Claude only; other providers keep their own caching.
|
|
227
|
+
Five minutes omits the wire `ttl` field, preserving the existing request. One
|
|
228
|
+
hour adds `ttl: "1h"` to the tools+system prefix and up to three conversation
|
|
229
|
+
breakpoints. All marks share one TTL: Anthropic rejects a one-hour mark after
|
|
230
|
+
a five-minute mark. Requests classified with `purpose` as compaction or
|
|
231
|
+
session-title keep five minutes. Unclassified calls, including subagents and
|
|
232
|
+
calls from hosts that do not supply `purpose`, follow the configured TTL.
|
|
233
|
+
The TTL setting does not require a newer host capability or dependency.
|
|
234
|
+
|
|
235
|
+
Cache reads have the same API price for either TTL. One-hour writes are priced
|
|
236
|
+
at 2× base input instead of 1.25×. They may pay off with reusable prefixes and
|
|
237
|
+
5–60-minute pauses; benefits depend on the workload and do not establish
|
|
238
|
+
subscription quota savings. Frequent reuse within five minutes may not offset
|
|
239
|
+
the higher write price. Claude Code requests one hour for its main subscription
|
|
240
|
+
conversation; see
|
|
241
|
+
[Claude Code's prompt-caching notes](https://code.claude.com/docs/en/prompt-caching#which-ttl-each-request-gets).
|
|
242
|
+
|
|
243
|
+
Changing TTL on a cached conversation may rewrite the prefix. Upstream testing
|
|
244
|
+
found that the first one-hour request after five-minute writes rewrote a
|
|
245
|
+
conversation-tail prefix, while a system-only breakpoint could hit. A
|
|
246
|
+
five-minute request can read a one-hour entry; a one-hour-marked read does not
|
|
247
|
+
upgrade an existing five-minute entry's lifetime. These observations are not
|
|
248
|
+
live-account verification of this fork.
|
|
249
|
+
|
|
186
250
|
## Usage coloring
|
|
187
251
|
|
|
188
252
|
**Settings → Subscriptions → Usage coloring** offers one browser-local dropdown:
|
package/lib/auth/device-flow.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* engines uniformly.
|
|
9
9
|
*/
|
|
10
10
|
import { hostFetch } from '../http.js';
|
|
11
|
+
import { parseProviderJson } from '../providers/common.js';
|
|
11
12
|
/** Default poll interval when the device-code response omits one. */
|
|
12
13
|
const DEFAULT_INTERVAL_SEC = 5;
|
|
13
14
|
/** Default device-code lifetime when the response omits one (GitHub: 15 minutes). */
|
|
@@ -77,7 +78,7 @@ export class DeviceFlowManager {
|
|
|
77
78
|
if (!response.ok) {
|
|
78
79
|
throw new Error(`${provider} device-code request failed (HTTP ${String(response.status)})`);
|
|
79
80
|
}
|
|
80
|
-
const wire = await response
|
|
81
|
+
const wire = await parseProviderJson(response, 'device code request');
|
|
81
82
|
if (typeof wire.device_code !== 'string' || wire.device_code.length === 0
|
|
82
83
|
|| typeof wire.user_code !== 'string' || wire.user_code.length === 0
|
|
83
84
|
|| typeof wire.verification_uri !== 'string' || wire.verification_uri.length === 0) {
|
|
@@ -133,7 +134,7 @@ export class DeviceFlowManager {
|
|
|
133
134
|
}).toString(),
|
|
134
135
|
signal: controller.signal,
|
|
135
136
|
});
|
|
136
|
-
const result = await pollResponse
|
|
137
|
+
const result = await parseProviderJson(pollResponse, 'device token poll');
|
|
137
138
|
if (typeof result.access_token === 'string' && result.access_token.length > 0) {
|
|
138
139
|
settle(undefined, result.access_token);
|
|
139
140
|
return;
|
|
@@ -152,7 +153,9 @@ export class DeviceFlowManager {
|
|
|
152
153
|
settle(new Error('the device code expired before authorization completed'));
|
|
153
154
|
return;
|
|
154
155
|
default:
|
|
155
|
-
|
|
156
|
+
// Safe means this failure path carries no provider-controlled free text,
|
|
157
|
+
// not that no secret can exist elsewhere in the system.
|
|
158
|
+
settle(new Error(`${provider} device-flow polling failed (HTTP ${String(pollResponse.status)}): [provider response body omitted]`));
|
|
156
159
|
return;
|
|
157
160
|
}
|
|
158
161
|
}
|
package/lib/auth/oauth-flow.js
CHANGED
|
@@ -12,6 +12,38 @@ export const DEFAULT_FLOW_TIMEOUT_MS = 180_000;
|
|
|
12
12
|
const SUCCESS_PAGE = '<!doctype html><html><head><meta charset="utf-8"><title>Login successful</title></head>'
|
|
13
13
|
+ '<body style="font-family:sans-serif"><h1>Login successful</h1>'
|
|
14
14
|
+ '<p>You can close this tab and return to DeepSeek Harness.</p></body></html>';
|
|
15
|
+
function authorizationFailure(error) {
|
|
16
|
+
// Safe means this failure path carries no provider-controlled free text,
|
|
17
|
+
// not that no secret can exist elsewhere in the system.
|
|
18
|
+
// RFC 6749 §4.1.2.1 categories select local literals, never provider prose.
|
|
19
|
+
let category;
|
|
20
|
+
switch (error) {
|
|
21
|
+
case 'invalid_request':
|
|
22
|
+
category = 'invalid_request';
|
|
23
|
+
break;
|
|
24
|
+
case 'unauthorized_client':
|
|
25
|
+
category = 'unauthorized_client';
|
|
26
|
+
break;
|
|
27
|
+
case 'access_denied':
|
|
28
|
+
category = 'access_denied';
|
|
29
|
+
break;
|
|
30
|
+
case 'unsupported_response_type':
|
|
31
|
+
category = 'unsupported_response_type';
|
|
32
|
+
break;
|
|
33
|
+
case 'invalid_scope':
|
|
34
|
+
category = 'invalid_scope';
|
|
35
|
+
break;
|
|
36
|
+
case 'server_error':
|
|
37
|
+
category = 'server_error';
|
|
38
|
+
break;
|
|
39
|
+
case 'temporarily_unavailable':
|
|
40
|
+
category = 'temporarily_unavailable';
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
return 'authorization failed'
|
|
44
|
+
+ (category === undefined ? '' : ` (${category})`)
|
|
45
|
+
+ ': [provider message omitted]';
|
|
46
|
+
}
|
|
15
47
|
function failurePage(detail) {
|
|
16
48
|
return '<!doctype html><html><head><meta charset="utf-8"><title>Login failed</title></head>'
|
|
17
49
|
+ `<body style="font-family:sans-serif"><h1>Login failed</h1><p>${detail.replace(/[<>&]/g, '')}</p></body></html>`;
|
|
@@ -138,19 +170,20 @@ export class OAuthFlowManager {
|
|
|
138
170
|
response.end('not found');
|
|
139
171
|
return;
|
|
140
172
|
}
|
|
141
|
-
const errorDescription = url.searchParams.get('error_description') ?? url.searchParams.get('error');
|
|
142
|
-
if (errorDescription !== null) {
|
|
143
|
-
response.writeHead(200, { 'content-type': 'text/html' });
|
|
144
|
-
response.end(failurePage(errorDescription));
|
|
145
|
-
settle(new Error(`authorization failed: ${errorDescription}`));
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
173
|
if (url.searchParams.get('state') !== input.state) {
|
|
149
|
-
// A stray or replayed redirect must not kill the real attempt.
|
|
174
|
+
// A stray or replayed redirect must not kill the real attempt, even on error.
|
|
175
|
+
// RFC 6749 §4.1.2.1 requires errors to echo the state sent in the request.
|
|
150
176
|
response.writeHead(400, { 'content-type': 'text/plain' });
|
|
151
177
|
response.end('state mismatch');
|
|
152
178
|
return;
|
|
153
179
|
}
|
|
180
|
+
if (url.searchParams.has('error_description') || url.searchParams.has('error')) {
|
|
181
|
+
const detail = authorizationFailure(url.searchParams.get('error'));
|
|
182
|
+
response.writeHead(200, { 'content-type': 'text/html' });
|
|
183
|
+
response.end(failurePage(detail));
|
|
184
|
+
settle(new Error(detail));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
154
187
|
const code = url.searchParams.get('code');
|
|
155
188
|
if (code === null || code.length === 0) {
|
|
156
189
|
response.writeHead(400, { 'content-type': 'text/plain' });
|
package/lib/auth/rpc.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare const SUBSCRIPTIONS_AUTH_PREFIX = "subscriptions-auth.";
|
|
|
23
23
|
* Every endpoint {@link dispatch} answers; each gets one exact Fetch route.
|
|
24
24
|
* Kept in one place so the route table and the switch cannot drift apart.
|
|
25
25
|
*/
|
|
26
|
-
export declare const SUBSCRIPTIONS_AUTH_ENDPOINTS: readonly ["providerSettings", "setProviderSettings", "status", "login", "manual", "cancel", "logout", "setDefault", "usage", "externalStatus", "externalUsage", "cursorStatus", "cursorLogin", "cursorCancel", "cursorLogout", "cursorUsage", "cursorModels", "cursorSettings", "cursorSetSettings", "image", "video", "speed", "setSpeed", "modelDefaults", "setModelDefault"];
|
|
26
|
+
export declare const SUBSCRIPTIONS_AUTH_ENDPOINTS: readonly ["providerSettings", "setProviderSettings", "status", "login", "manual", "cancel", "logout", "setDefault", "usage", "externalStatus", "externalUsage", "cursorStatus", "cursorLogin", "cursorCancel", "cursorLogout", "cursorUsage", "cursorModels", "cursorSettings", "cursorSetSettings", "image", "video", "prepareReset", "consumeReset", "speed", "setSpeed", "modelDefaults", "setModelDefault"];
|
|
27
27
|
/** Decoded image bytes returned by the `image` endpoint. */
|
|
28
28
|
export interface ImageBytesResult {
|
|
29
29
|
mediaType: string;
|
|
@@ -121,6 +121,8 @@ export interface ModelDefaultsController {
|
|
|
121
121
|
}
|
|
122
122
|
/** Provider-agnostic auth operations the RPC handler delegates to. */
|
|
123
123
|
export interface AuthController {
|
|
124
|
+
prepareReset?(account: string, signal: AbortSignal): Promise<unknown>;
|
|
125
|
+
consumeReset?(account: string, ticket: string, signal: AbortSignal): Promise<void>;
|
|
124
126
|
/** Current status of one provider. */
|
|
125
127
|
status(provider: ProviderId): Promise<ProviderStatus>;
|
|
126
128
|
/**
|
package/lib/auth/rpc.js
CHANGED
|
@@ -25,7 +25,7 @@ export const SUBSCRIPTIONS_AUTH_ENDPOINTS = [
|
|
|
25
25
|
'externalStatus', 'externalUsage',
|
|
26
26
|
'cursorStatus', 'cursorLogin', 'cursorCancel', 'cursorLogout', 'cursorUsage', 'cursorModels',
|
|
27
27
|
'cursorSettings', 'cursorSetSettings',
|
|
28
|
-
'image', 'video',
|
|
28
|
+
'image', 'video', 'prepareReset', 'consumeReset',
|
|
29
29
|
'speed', 'setSpeed',
|
|
30
30
|
'modelDefaults', 'setModelDefault',
|
|
31
31
|
];
|
|
@@ -322,6 +322,15 @@ async function dispatch(controller, speed, modelDefaults, endpoint, payload, sig
|
|
|
322
322
|
throw new BadRequest('payload must be an object');
|
|
323
323
|
await cursor.setSettings(payload.settings);
|
|
324
324
|
return ok({ ok: true });
|
|
325
|
+
case 'prepareReset':
|
|
326
|
+
if (!controller.prepareReset)
|
|
327
|
+
throw new BadRequest('Reset redemption unavailable');
|
|
328
|
+
return ok(await controller.prepareReset(readString(payload, 'account'), signal));
|
|
329
|
+
case 'consumeReset':
|
|
330
|
+
if (!controller.consumeReset)
|
|
331
|
+
throw new BadRequest('Reset redemption unavailable');
|
|
332
|
+
await controller.consumeReset(readString(payload, 'account'), readString(payload, 'ticket'), signal);
|
|
333
|
+
return ok({ ok: true });
|
|
325
334
|
case 'image':
|
|
326
335
|
return ok(await controller.readImage(readImageRef(payload), signal));
|
|
327
336
|
case 'video':
|
|
@@ -3,13 +3,8 @@ import { useEffect, useId, useRef, useState } from 'react';
|
|
|
3
3
|
import { callSubscriptionsAuth } from './subscriptions-rpc.js';
|
|
4
4
|
import { accountModelRows, accountPoolSelection, mergeAccountChanges, mergeLatestAccounts } from './account-preferences.js';
|
|
5
5
|
import { ProviderModelEditor } from './ProviderModelEditor.js';
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
font: 'inherit', color: 'inherit', background: 'var(--dsw-alias-bg-layer-1)',
|
|
9
|
-
border, borderRadius: 8, padding: '7px 12px', minWidth: 0,
|
|
10
|
-
};
|
|
11
|
-
const button = { ...control, cursor: 'pointer' };
|
|
12
|
-
const hint = { margin: 0, fontSize: 12, lineHeight: 1.6, color: 'var(--dsw-alias-label-tertiary)' };
|
|
6
|
+
import { providerSettingsCss } from './provider-settings-styles.js';
|
|
7
|
+
const border = '0.5px solid var(--dsw-alias-border-l2)';
|
|
13
8
|
const stack = { display: 'grid', gap: 12, minWidth: 0 };
|
|
14
9
|
const actions = { display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' };
|
|
15
10
|
/** Native top-layer dialog provides keyboard containment, Escape and focus restoration. */
|
|
@@ -110,38 +105,36 @@ export function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
110
105
|
setSaving(false);
|
|
111
106
|
}
|
|
112
107
|
}
|
|
113
|
-
return
|
|
114
|
-
event.preventDefault(); }, onClose: onClose, style: { width: 620, maxWidth: 'calc(100vw - 32px)', maxHeight: 'calc(100dvh - 32px)',
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
_jsx(ProviderModelEditor, { ref: editor, provider: provider, rpc: rpc, t: t, disabled: saving, onDirtyChange: setModelsDirty }), _jsxs("footer", { style: { ...stack, gap: 8, borderTop: border, padding: '14px 0 0',
|
|
146
|
-
position: 'sticky', bottom: 0, background: 'var(--dsw-alias-bg-layer-1)' }, children: [saveError && _jsx("p", { role: "alert", style: { ...hint, color: 'var(--dsw-alias-state-error-primary)' }, children: saveError }), _jsxs("div", { style: { ...actions, justifyContent: 'flex-end' }, children: [_jsx("button", { type: "button", style: button, disabled: saving, onClick: onClose, children: t('cancel') }), _jsx("button", { type: "button", style: { ...button, fontWeight: 600 }, disabled: loading || saving || (!Object.keys(changes).length && !modelsDirty), onClick: () => { void save(); }, children: saving ? t('modelDefaultsSaving') : t('modelsSave') })] })] })] }) });
|
|
108
|
+
return _jsxs("dialog", { className: "dsh-subscription-manager", ref: dialog, "aria-labelledby": title, "aria-describedby": description, onCancel: event => { if (saveLock.current)
|
|
109
|
+
event.preventDefault(); }, onClose: onClose, style: { width: 620, maxWidth: 'calc(100vw - 32px)', maxHeight: 'calc(100dvh - 32px)', overflow: 'auto' }, children: [_jsx("style", { children: providerSettingsCss }), _jsxs("div", { style: { ...stack, padding: 20 }, children: [_jsxs("header", { style: { ...actions, justifyContent: 'space-between' }, children: [_jsx("h2", { id: title, style: { margin: 0 }, children: t('accountsTitle', { provider: name }) }), _jsx("button", { type: "button", autoFocus: true, disabled: saving, onClick: onClose, children: t('imageClose') })] }), _jsx("p", { id: description, className: "dsh-subscription-hint", children: t(provider === 'cursor-subscription' ? 'cursorAccountsHint' : 'accountsHint') }), error && _jsx("p", { role: "alert", children: error }), loading && _jsx("p", { role: "status", className: "dsh-subscription-hint", children: t('accountsLoading') }), !loading && !catalog && _jsx("button", { type: "button", onClick: () => setAttempt(value => value + 1), children: t('modelDefaultsRetry') }), catalog && _jsxs("fieldset", { disabled: saving || loading, style: { ...stack, border: 0, margin: 0, padding: 0 }, children: [catalog.accounts.length === 0 && _jsx("p", { className: "dsh-subscription-hint", children: t(provider === 'cursor-subscription' ? 'cursorManageSignIn' : 'accountsEmpty') }), provider === 'cursor-subscription' && catalog.accounts.length > 0 &&
|
|
110
|
+
_jsxs("fieldset", { style: { border, borderRadius: 'var(--dsw-radius-lg, 12px)', padding: 14 }, children: [_jsx("legend", { style: { padding: '0 6px' }, children: name }), _jsx("p", { className: "dsh-subscription-hint", children: t('cursorConnected') })] }), provider !== 'cursor-subscription' && catalog.accounts.map(account => {
|
|
111
|
+
const preferences = changes[account.key] ?? catalog.settings.accounts?.[account.key] ?? {};
|
|
112
|
+
const selected = accountPoolSelection(preferences, account.models);
|
|
113
|
+
const models = accountModelRows(account, preferences);
|
|
114
|
+
return _jsxs("fieldset", { style: { ...stack, border, borderRadius: 'var(--dsw-radius-lg, 12px)', padding: 14, margin: 0 }, children: [_jsx("legend", { style: { padding: '0 6px', overflowWrap: 'anywhere', maxWidth: '100%' }, children: account.label }), account.unavailable && _jsx("p", { className: "dsh-subscription-hint", children: t('accountsCatalogUnavailable') }), _jsxs("label", { style: { ...stack, gap: 6 }, children: [_jsx("span", { className: "dsh-subscription-label", children: t('accountsAlias') }), _jsx("input", { value: preferences.alias ?? '', placeholder: account.label, onChange: event => {
|
|
115
|
+
const next = { ...preferences };
|
|
116
|
+
if (event.target.value.trim())
|
|
117
|
+
next.alias = event.target.value;
|
|
118
|
+
else
|
|
119
|
+
delete next.alias;
|
|
120
|
+
edit(account.key, next);
|
|
121
|
+
} })] }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.poolEnabled !== false, onChange: event => edit(account.key, { ...preferences, poolEnabled: event.target.checked }) }), " ", t('accountsPoolEnabled')] }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.independentEntry === true, onChange: event => edit(account.key, { ...preferences, independentEntry: event.target.checked }) }), " ", t('accountsIndependent')] }), _jsx("p", { className: "dsh-subscription-hint", children: t('accountsIndependentHint') }), _jsxs("details", { children: [_jsxs("summary", { style: { cursor: 'pointer', fontSize: 13 }, children: [t('accountsModels'), " \u00B7 ", preferences.poolModels === undefined
|
|
122
|
+
? t('accountsModelsAll') : t('accountsModelsCount', { count: preferences.poolModels.length })] }), _jsxs("div", { style: { ...stack, marginTop: 12 }, children: [_jsx("p", { className: "dsh-subscription-hint", children: t('accountsModelsHint') }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: preferences.poolModels === undefined, onChange: event => {
|
|
123
|
+
const next = { ...preferences };
|
|
124
|
+
if (event.target.checked)
|
|
125
|
+
delete next.poolModels;
|
|
126
|
+
else
|
|
127
|
+
next.poolModels = account.models.map(model => model.id);
|
|
128
|
+
edit(account.key, next);
|
|
129
|
+
} }), " ", t('accountsModelsAutomatic')] }), _jsxs("div", { style: actions, children: [_jsx("button", { type: "button", onClick: () => edit(account.key, { ...preferences, poolModels: models.map(model => model.id) }), children: t('modelsSelectAll') }), _jsx("button", { type: "button", onClick: () => edit(account.key, { ...preferences, poolModels: [] }), children: t('modelsSelectNone') })] }), _jsxs("div", { style: { ...stack, gap: 8, maxHeight: 240, overflowY: 'auto' }, children: [models.map(model => _jsxs("label", { style: { overflowWrap: 'anywhere' }, children: [_jsx("input", { type: "checkbox", checked: selected.has(model.id), onChange: event => {
|
|
130
|
+
const next = new Set(selected);
|
|
131
|
+
if (event.target.checked)
|
|
132
|
+
next.add(model.id);
|
|
133
|
+
else
|
|
134
|
+
next.delete(model.id);
|
|
135
|
+
edit(account.key, { ...preferences, poolModels: [...next] });
|
|
136
|
+
} }), " ", model.name, model.unavailable && ` (${t('modelsUnavailable')})`] }, model.id)), models.length === 0 && _jsx("p", { className: "dsh-subscription-hint", children: t('accountsNoModels') })] })] })] })] }, account.key);
|
|
137
|
+
})] }), (provider !== 'cursor-subscription' || (catalog?.accounts.length ?? 0) > 0) &&
|
|
138
|
+
_jsx(ProviderModelEditor, { ref: editor, provider: provider, rpc: rpc, t: t, disabled: saving, onDirtyChange: setModelsDirty }), _jsxs("footer", { style: { ...stack, gap: 8, borderTop: border, padding: '14px 0 8px',
|
|
139
|
+
position: 'sticky', bottom: 0, background: 'var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1))' }, children: [saveError && _jsx("p", { role: "alert", children: saveError }), _jsxs("div", { style: { ...actions, justifyContent: 'flex-end' }, children: [_jsx("button", { type: "button", disabled: saving, onClick: onClose, children: t('cancel') }), _jsx("button", { type: "button", className: "dsh-subscription-primary", disabled: loading || saving || (!Object.keys(changes).length && !modelsDirty), onClick: () => { void save(); }, children: saving ? t('modelDefaultsSaving') : t('modelsSave') })] })] })] })] });
|
|
147
140
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
3
3
|
import { callSubscriptionsAuth } from './subscriptions-rpc.js';
|
|
4
|
-
const border = '
|
|
5
|
-
const control = {
|
|
6
|
-
font: 'inherit', color: 'inherit', background: 'transparent', border,
|
|
7
|
-
borderRadius: 8, padding: '6px 10px', minWidth: 0,
|
|
8
|
-
};
|
|
4
|
+
const border = '0.5px solid var(--dsw-alias-border-l2, #ddd)';
|
|
9
5
|
const actions = { display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' };
|
|
10
6
|
/**
|
|
11
7
|
* Embedded section of the account manager dialog. It owns the model draft
|
|
@@ -83,25 +79,25 @@ export const ProviderModelEditor = forwardRef(function ProviderModelEditor({ pro
|
|
|
83
79
|
const missing = (draft.visibleModels ?? []).filter(id => !known.has(id)).map(id => ({ id, name: id }));
|
|
84
80
|
const models = [...allModels, ...missing].filter(model => `${model.name} ${model.id}`.toLowerCase().includes(query.trim().toLowerCase()));
|
|
85
81
|
const selected = new Set(draft.visibleModels ?? allModels.map(model => model.id));
|
|
86
|
-
return _jsxs("div", { style: { borderTop: border, marginTop: 12, paddingTop: 12 }, children: [_jsx("h3", { style: { margin: 0
|
|
82
|
+
return _jsxs("div", { style: { borderTop: border, marginTop: 12, paddingTop: 12 }, children: [_jsx("h3", { style: { margin: 0 }, children: t('modelsEdit') }), _jsxs("div", { style: { display: 'grid', gap: 12, marginTop: 12 }, children: [_jsx("p", { className: "dsh-subscription-hint", children: t(provider === 'cursor-subscription' ? 'cursorManageHint' : 'modelsHint') }), error && _jsx("p", { role: "alert", children: error }), _jsxs("div", { style: actions, children: [_jsx("button", { type: "button", className: "dsh-subscription-quiet", disabled: busy || disabled || dirty, onClick: () => { void load(true); }, children: t('usageRefresh') }), busy && _jsx("span", { role: "status", children: t('modelDefaultsLoading') })] }), catalog && _jsxs("fieldset", { disabled: busy || disabled, style: { border: 0, padding: 0, margin: 0, minWidth: 0, display: 'grid', gap: 12 }, children: [_jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: draft.visibleModels === undefined, onChange: event => {
|
|
87
83
|
const next = { ...draft };
|
|
88
84
|
if (event.target.checked)
|
|
89
85
|
delete next.visibleModels;
|
|
90
86
|
else
|
|
91
87
|
next.visibleModels = allModels.map(model => model.id);
|
|
92
88
|
edit(next);
|
|
93
|
-
} }), " ", t('modelsAutomatic')] }), _jsxs("div", { style: actions, children: [_jsx("input", { style: {
|
|
89
|
+
} }), " ", t('modelsAutomatic')] }), _jsxs("div", { style: actions, children: [_jsx("input", { style: { flex: '1 1 180px' }, value: query, onChange: event => setQuery(event.target.value), placeholder: t('modelDefaultsFilterPlaceholder'), "aria-label": t('modelDefaultsFilterPlaceholder') }), _jsx("button", { type: "button", onClick: () => edit({ ...draft, visibleModels: allModels.map(model => model.id) }), children: t('modelsSelectAll') }), _jsx("button", { type: "button", onClick: () => edit({ ...draft, visibleModels: [] }), children: t('modelsSelectNone') })] }), _jsxs("div", { style: { maxHeight: 360, overflowY: 'auto', display: 'grid', gap: 8 }, children: [models.map(model => _jsxs("div", { style: { borderBottom: border, padding: '8px 2px', display: 'grid', gap: 8 }, children: [_jsxs("label", { style: { overflowWrap: 'anywhere' }, children: [_jsx("input", { type: "checkbox", checked: selected.has(model.id), onChange: event => {
|
|
94
90
|
const next = new Set(selected);
|
|
95
91
|
if (event.target.checked)
|
|
96
92
|
next.add(model.id);
|
|
97
93
|
else
|
|
98
94
|
next.delete(model.id);
|
|
99
95
|
edit({ ...draft, visibleModels: [...next] });
|
|
100
|
-
} }), " ", model.name, !known.has(model.id) && ` (${t('modelsUnavailable')})`] }), _jsxs("div", { style: actions, children: [(model.efforts?.length ?? 0) > 0 && _jsxs("label", { style: actions, children: [t('modelDefaultsTitle'), _jsxs("select", {
|
|
96
|
+
} }), " ", model.name, !known.has(model.id) && ` (${t('modelsUnavailable')})`] }), _jsxs("div", { style: actions, children: [(model.efforts?.length ?? 0) > 0 && _jsxs("label", { style: actions, children: [t('modelDefaultsTitle'), _jsxs("select", { "aria-label": `${model.name} ${t('modelDefaultsTitle')}`, value: efforts[model.id] ?? '', onChange: event => {
|
|
101
97
|
setEfforts({ ...efforts, [model.id]: event.target.value });
|
|
102
98
|
setDirty(true);
|
|
103
99
|
}, children: [_jsx("option", { value: "", children: t('modelDefaultsFollowProvider') }), model.configured && !model.efforts?.some(effort => effort.id === model.configured) &&
|
|
104
|
-
_jsxs("option", { value: model.configured, disabled: true, children: [model.configured, " (", t('modelsUnavailable'), ")"] }), model.efforts?.map(effort => _jsx("option", { value: effort.id, children: effort.name }, effort.id))] })] }), provider === 'codex' && model.maxContextWindow !== undefined && _jsxs("div", { style: actions, children: [_jsxs("label", { style: actions, children: [t('modelsContext'), _jsx("input", { style: {
|
|
100
|
+
_jsxs("option", { value: model.configured, disabled: true, children: [model.configured, " (", t('modelsUnavailable'), ")"] }), model.efforts?.map(effort => _jsx("option", { value: effort.id, children: effort.name }, effort.id))] })] }), provider === 'codex' && model.maxContextWindow !== undefined && _jsxs("div", { style: actions, children: [_jsxs("label", { style: actions, children: [t('modelsContext'), _jsx("input", { style: { width: 140 }, inputMode: "numeric", value: contexts[model.id] ?? '', "aria-label": `${model.name} ${t('modelsContext')}`, placeholder: String(model.defaultContextWindow), onChange: event => { setContexts({ ...contexts, [model.id]: event.target.value }); setDirty(true); } })] }), _jsx("small", { children: t('modelsContextBounds', { default: model.defaultContextWindow, max: model.maxContextWindow }) })] })] })] }, model.id)), models.length === 0 && _jsx("span", { children: t('modelDefaultsFilterEmpty', { query }) })] }), provider === 'codex' && _jsx("small", { children: t('modelsContextHint') }), catalog.tools.length > 0 && _jsxs("div", { style: { display: 'grid', gap: 8 }, children: [_jsx("strong", { children: t('modelsTools') }), _jsx("small", { children: t('modelsToolsHint') }), catalog.tools.map(tool => _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: draft.tools?.[tool] !== false, onChange: event => edit({
|
|
105
101
|
...draft, tools: { ...draft.tools, [tool]: event.target.checked },
|
|
106
102
|
}) }), " ", t(tool === 'image_generate' ? 'modelsImage' : tool === 'video_generate' ? 'modelsVideo' : tool === 'web_search' ? 'modelsWebSearch' : 'modelsSearch')] }, tool))] })] })] })] });
|
|
107
103
|
});
|
|
@@ -14,6 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
14
14
|
*/
|
|
15
15
|
import { useEffect, useRef, useState } from 'react';
|
|
16
16
|
import { callSubscriptionsAuth } from './SubscriptionsSection.js';
|
|
17
|
+
import { subscriptionChromeCss } from './provider-settings-styles.js';
|
|
17
18
|
import { en } from './locales.js';
|
|
18
19
|
/**
|
|
19
20
|
* The `loadSpeed` half of the inject face: the plugin's own speed state plus
|
|
@@ -136,12 +137,12 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
|
|
|
136
137
|
const tierName = (tier) => translate(tier === 'fast' ? 'speedFast' : 'speedStandard');
|
|
137
138
|
const tierDescription = (tier) => translate(tier === 'fast' ? 'speedFastDescription' : 'speedStandardDescription');
|
|
138
139
|
const triggerLabel = `${translate('speed')} · ${tierName(state.tier)}`;
|
|
139
|
-
return (_jsxs("div", { ref: rootRef, style: styles.root, onKeyDown: (event) => {
|
|
140
|
+
return (_jsxs("div", { ref: rootRef, className: "dsh-subscription-speed", style: styles.root, onKeyDown: (event) => {
|
|
140
141
|
if (event.key === 'Escape' && open) {
|
|
141
142
|
event.preventDefault();
|
|
142
143
|
setOpen(false);
|
|
143
144
|
}
|
|
144
|
-
}, children: [open && (_jsx("div", { style: styles.menu, role: "menu", "aria-label": translate('speed'), children: TIERS.map(tier => (_jsxs("button", { type: "button", role: "menuitemradio", "aria-checked": tier === state.tier, style: styles.item, disabled: busy, onClick: () => { choose(tier); }, children: [_jsx("span", { style: styles.itemCheck, children: tier === state.tier ? '✓' : '' }), _jsxs("span", { style: styles.itemText, children: [_jsx("span", { style: styles.itemName, children: tierName(tier) }), _jsx("span", { style: styles.itemDescription, children: tierDescription(tier) })] })] }, tier))) })), _jsx("button", { type: "button", style: styles.trigger, "aria-haspopup": "menu", "aria-expanded": open, title: triggerLabel, disabled: busy, onClick: () => {
|
|
145
|
+
}, children: [_jsx("style", { children: subscriptionChromeCss }), open && (_jsx("div", { style: styles.menu, role: "menu", "aria-label": translate('speed'), children: TIERS.map(tier => (_jsxs("button", { type: "button", role: "menuitemradio", "aria-checked": tier === state.tier, style: styles.item, disabled: busy, onClick: () => { choose(tier); }, children: [_jsx("span", { style: styles.itemCheck, children: tier === state.tier ? '✓' : '' }), _jsxs("span", { style: styles.itemText, children: [_jsx("span", { style: styles.itemName, children: tierName(tier) }), _jsx("span", { style: styles.itemDescription, children: tierDescription(tier) })] })] }, tier))) })), _jsx("button", { type: "button", style: styles.trigger, "aria-haspopup": "menu", "aria-expanded": open, title: triggerLabel, disabled: busy, onClick: () => {
|
|
145
146
|
if (open)
|
|
146
147
|
setOpen(false);
|
|
147
148
|
else
|
|
@@ -151,20 +152,20 @@ export function SpeedSelect({ loadSpeed, setSpeed, t }) {
|
|
|
151
152
|
const styles = {
|
|
152
153
|
root: { position: 'relative', display: 'inline-flex' },
|
|
153
154
|
trigger: {
|
|
154
|
-
border: '
|
|
155
|
-
background: 'transparent', color: 'var(--dsw-alias-label-secondary)',
|
|
155
|
+
border: '0.5px solid var(--dsw-alias-border-l3)', borderRadius: 'var(--dsw-radius-sm, 8px)',
|
|
156
|
+
background: 'var(--dsh-subscription-speed-hover, transparent)', color: 'var(--dsw-alias-label-secondary)',
|
|
156
157
|
font: 'inherit', fontSize: 12, lineHeight: '18px',
|
|
157
158
|
padding: '2px 8px', cursor: 'pointer', whiteSpace: 'nowrap',
|
|
158
159
|
},
|
|
159
160
|
menu: {
|
|
160
161
|
position: 'absolute', bottom: '100%', right: 0, marginBottom: 4,
|
|
161
162
|
minWidth: 180, padding: 4, zIndex: 20,
|
|
162
|
-
background: 'var(--dsw-
|
|
163
|
-
borderRadius:
|
|
163
|
+
background: 'var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2))', border: 0,
|
|
164
|
+
boxShadow: 'var(--dsw-elevation-prominent)', borderRadius: 'var(--dsw-radius-lg, 16px)', display: 'flex', flexDirection: 'column', gap: 2,
|
|
164
165
|
},
|
|
165
166
|
item: {
|
|
166
167
|
display: 'flex', alignItems: 'flex-start', gap: 6, width: '100%',
|
|
167
|
-
border: 'none', borderRadius:
|
|
168
|
+
border: 'none', borderRadius: 'var(--dsw-radius-sm, 8px)', background: 'var(--dsh-subscription-speed-hover, transparent)',
|
|
168
169
|
padding: '6px 8px', cursor: 'pointer', font: 'inherit', textAlign: 'left',
|
|
169
170
|
},
|
|
170
171
|
itemCheck: {
|
|
@@ -24,6 +24,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
24
24
|
* 'settings.subscriptions' namespace.
|
|
25
25
|
*/
|
|
26
26
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
27
|
+
import { subscriptionChromeCss } from './provider-settings-styles.js';
|
|
27
28
|
import { createPortal } from 'react-dom';
|
|
28
29
|
import * as primitives from '@deepseek-ai/dsh-client-ui-primitives';
|
|
29
30
|
import { useAnchoredPosition, useDismissOnOutsidePointer } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
@@ -513,7 +514,7 @@ export function SubscriptionUsageBadge({ rpc, currentModel, t, rotationMs }) {
|
|
|
513
514
|
if (next)
|
|
514
515
|
void refresh();
|
|
515
516
|
};
|
|
516
|
-
const pill = (_jsxs("span", { ref: rootRef, style: styles.anchor, children: [_jsxs("button", { type: "button", style: { ...styles.pill, ...(hover || open ? styles.pillActive : {}) }, "aria-haspopup": "dialog", "aria-expanded": open, "aria-label": `${title} · ${label}`, title: title, onMouseEnter: () => { setHover(true); }, onMouseLeave: () => { setHover(false); }, onClick: toggle, children: [_jsx(UsageBadgeIcon, {}), _jsx("span", { style: styles.label, children: label })] }), open && createPortal(_jsxs("div", { ref: panelRef, role: "dialog", "aria-label": title, style: { ...styles.panel, ...(pos ?? MEASURE_STYLE) }, children: [_jsx("div", { style: styles.title, children: _jsxs("span", { style: styles.titleLabel, children: [_jsx(UsageBadgeIcon, {}), title] }) }), _jsx("div", { style: styles.titleRule, "aria-hidden": true }), expanded.map((d, index) => (_jsxs("section", { style: index === 0 ? undefined : styles.section, children: [_jsxs("div", { style: styles.providerRow, children: [_jsxs("span", { style: styles.providerName, children: [d.name, d.provider === current && _jsx("span", { style: styles.currentTag, children: translate('usageBadgeCurrent') })] }), d.accounts.length === 1 && _jsx(AccountMeta, { account: d.accounts[0], translate: translate })] }), d.accounts.map((account, accountIndex) => (_jsxs("div", { style: accountIndex === 0 ? undefined : styles.accountBlock, children: [d.accounts.length > 1 && (_jsx("div", { style: styles.accountRow, children: _jsx(AccountMeta, { account: account, translate: translate }) })), _jsx(AccountWindows, { windows: account.windows, observedAt: account.observedAt, stale: account.stale, model: d.provider === dialogProvider ? dialogModel : undefined, provider: d.provider, translate: translate }, `${d.provider}:${dialogModel ?? ''}`)] }, account.key)))] }, d.provider)))] }), document.body)] }));
|
|
517
|
+
const pill = (_jsxs("span", { ref: rootRef, style: styles.anchor, children: [_jsx("style", { children: subscriptionChromeCss }), _jsxs("button", { type: "button", className: "dsh-subscription-usage-pill", style: { ...styles.pill, ...(hover || open ? styles.pillActive : {}) }, "aria-haspopup": "dialog", "aria-expanded": open, "aria-label": `${title} · ${label}`, title: title, onMouseEnter: () => { setHover(true); }, onMouseLeave: () => { setHover(false); }, onClick: toggle, children: [_jsx(UsageBadgeIcon, {}), _jsx("span", { style: styles.label, children: label })] }), open && createPortal(_jsxs("div", { ref: panelRef, role: "dialog", "aria-label": title, className: "dsh-subscription-usage-panel", style: { ...styles.panel, ...(pos ?? MEASURE_STYLE) }, children: [_jsx("div", { style: styles.title, children: _jsxs("span", { style: styles.titleLabel, children: [_jsx(UsageBadgeIcon, {}), title] }) }), _jsx("div", { style: styles.titleRule, "aria-hidden": true }), expanded.map((d, index) => (_jsxs("section", { style: index === 0 ? undefined : styles.section, children: [_jsxs("div", { style: styles.providerRow, children: [_jsxs("span", { style: styles.providerName, children: [d.name, d.provider === current && _jsx("span", { style: styles.currentTag, children: translate('usageBadgeCurrent') })] }), d.accounts.length === 1 && _jsx(AccountMeta, { account: d.accounts[0], translate: translate })] }), d.accounts.map((account, accountIndex) => (_jsxs("div", { style: accountIndex === 0 ? undefined : styles.accountBlock, children: [d.accounts.length > 1 && (_jsx("div", { style: styles.accountRow, children: _jsx(AccountMeta, { account: account, translate: translate }) })), _jsx(AccountWindows, { windows: account.windows, observedAt: account.observedAt, stale: account.stale, model: d.provider === dialogProvider ? dialogModel : undefined, provider: d.provider, translate: translate }, `${d.provider}:${dialogModel ?? ''}`)] }, account.key)))] }, d.provider)))] }), document.body)] }));
|
|
517
518
|
return (_jsxs(_Fragment, { children: [seat, statsRow !== null && statsRow.isConnected ? createPortal(pill, statsRow) : pill] }));
|
|
518
519
|
}
|
|
519
520
|
/**
|
|
@@ -564,9 +565,9 @@ const styles = {
|
|
|
564
565
|
pill: {
|
|
565
566
|
boxSizing: 'border-box', maxWidth: '100%',
|
|
566
567
|
color: 'var(--dsw-alias-label-tertiary)',
|
|
567
|
-
font: 'inherit', fontSize: 'var(--dsh-content-font-size-secondary, 13px)',
|
|
568
|
-
fontVariantNumeric: 'tabular-nums', lineHeight: '20px', whiteSpace: 'nowrap',
|
|
569
|
-
background: 'transparent', border: 'none', borderRadius:
|
|
568
|
+
font: 'inherit', fontSize: 'calc(var(--dsh-content-font-size-secondary, 13px) - 1px)',
|
|
569
|
+
fontVariantNumeric: 'tabular-nums', lineHeight: 'calc(20px + var(--dsh-content-font-delta-secondary, 0px))', whiteSpace: 'nowrap',
|
|
570
|
+
background: 'transparent', border: 'none', borderRadius: 999,
|
|
570
571
|
alignItems: 'center', gap: 6, padding: '1px 8px', display: 'inline-flex', cursor: 'pointer',
|
|
571
572
|
},
|
|
572
573
|
pillActive: {
|
|
@@ -586,7 +587,7 @@ const styles = {
|
|
|
586
587
|
maxHeight: 'min(560px, 100dvh - 24px)', overflowY: 'auto', overscrollBehavior: 'contain',
|
|
587
588
|
boxShadow: 'var(--dsw-elevation-prominent)',
|
|
588
589
|
color: 'var(--dsw-alias-label-secondary)', cursor: 'default',
|
|
589
|
-
border: 0, borderRadius:
|
|
590
|
+
border: 0, borderRadius: 'var(--dsw-radius-lg, 16px)', padding: 16, fontSize: 12, lineHeight: '18px',
|
|
590
591
|
},
|
|
591
592
|
title: {
|
|
592
593
|
color: 'var(--dsw-alias-label-primary)', display: 'flex',
|