dsh-subscriptions 0.2.0 → 0.2.2
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 +212 -180
- package/lib/auth/claude-code-creds.js +31 -9
- package/lib/auth/device-flow.js +16 -9
- package/lib/auth/oauth-flow.js +13 -10
- package/lib/auth/rpc.js +74 -23
- package/lib/auth/store.js +80 -31
- package/lib/client/CursorCard.d.ts +1 -1
- package/lib/client/CursorCard.js +50 -16
- package/lib/client/ExternalUsageCards.d.ts +1 -1
- package/lib/client/ExternalUsageCards.js +37 -16
- package/lib/client/ImageGallery.d.ts +2 -2
- package/lib/client/ImageGallery.js +92 -33
- package/lib/client/ImageGenerateToolview.js +50 -14
- package/lib/client/OllamaCard.d.ts +1 -1
- package/lib/client/OllamaCard.js +26 -8
- package/lib/client/OllamaSettingsManager.js +113 -30
- package/lib/client/ProviderAccountManager.d.ts +1 -1
- package/lib/client/ProviderAccountManager.js +164 -49
- package/lib/client/ProviderModelEditor.js +107 -26
- package/lib/client/SpeedSelect.d.ts +62 -14
- package/lib/client/SpeedSelect.js +257 -46
- package/lib/client/SubscriptionUsageBadge.d.ts +4 -10
- package/lib/client/SubscriptionUsageBadge.js +300 -112
- package/lib/client/SubscriptionsSection.js +258 -85
- package/lib/client/UsageBadgeDisplaySetting.js +35 -12
- package/lib/client/UsageMeter.d.ts +1 -1
- package/lib/client/UsageMeter.js +62 -24
- package/lib/client/VideoGenerateToolview.js +69 -17
- package/lib/client/account-preferences.d.ts +8 -0
- package/lib/client/account-preferences.js +20 -5
- package/lib/client/host-contract.d.ts +11 -2
- package/lib/client/host-contract.js +20 -3
- package/lib/client/index.d.ts +5 -5
- package/lib/client/index.js +34 -12
- package/lib/client/locales.d.ts +10 -0
- package/lib/client/locales.js +61 -51
- package/lib/client/ollama-draft.js +21 -12
- package/lib/client/reset-action.js +6 -4
- package/lib/client/reset-credits-view.d.ts +1 -1
- package/lib/client/reset-credits-view.js +66 -17
- package/lib/client/subscription-card-styles.js +94 -24
- package/lib/client/usage-color-preferences.js +4 -2
- package/lib/client/usage-pace.js +30 -12
- package/lib/client.js +287 -47
- package/lib/client.js.map +1 -1
- package/lib/http.js +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.js +118 -64
- package/lib/model-defaults.js +4 -2
- package/lib/provider-settings.d.ts +12 -0
- package/lib/provider-settings.js +58 -16
- package/lib/providers/account-preferences.js +51 -22
- package/lib/providers/accounts.js +15 -9
- package/lib/providers/antigravity-oauth-client.js +2 -2
- package/lib/providers/antigravity.js +141 -68
- package/lib/providers/catalog-store.js +120 -41
- package/lib/providers/claude-cli-version.js +3 -3
- package/lib/providers/claude.d.ts +9 -2
- package/lib/providers/claude.js +153 -90
- package/lib/providers/codex-client-version.js +3 -3
- package/lib/providers/codex-search.js +40 -13
- package/lib/providers/codex.js +196 -112
- package/lib/providers/common.js +71 -39
- package/lib/providers/copilot.js +143 -82
- package/lib/providers/cursor-adapter.js +42 -18
- package/lib/providers/cursor-auth.d.ts +1 -1
- package/lib/providers/cursor-auth.js +69 -24
- package/lib/providers/cursor-model-settings.js +14 -5
- package/lib/providers/cursor-usage.js +27 -13
- package/lib/providers/external-usage-controller.js +14 -5
- package/lib/providers/external-usage.js +59 -23
- package/lib/providers/grok.js +152 -89
- package/lib/providers/image-pool.js +29 -11
- package/lib/providers/minimax-usage.js +31 -11
- package/lib/providers/npm-cli-version.js +10 -3
- package/lib/providers/ollama-settings.js +24 -8
- package/lib/providers/ollama-web.js +29 -11
- package/lib/providers/ollama.js +129 -66
- package/lib/providers/pool-family.js +11 -3
- package/lib/providers/pool-health.js +28 -8
- package/lib/providers/pool-usage.js +16 -9
- package/lib/providers/pool.d.ts +8 -0
- package/lib/providers/pool.js +81 -42
- package/lib/providers/rate-limit.js +8 -2
- package/lib/providers/replay.js +40 -17
- package/lib/providers/reset-redemption.js +18 -6
- package/lib/tools/image-generate.js +123 -65
- package/lib/tools/registration.js +5 -2
- package/lib/tools/video-generate.js +51 -31
- package/lib/tools/x-search.js +50 -22
- package/lib/translate/anthropic.js +85 -37
- package/lib/translate/antigravity-schema.js +71 -28
- package/lib/translate/antigravity-thinking.js +22 -9
- package/lib/translate/antigravity.js +141 -50
- package/lib/translate/chat-completions.js +67 -23
- package/lib/translate/resolved.js +55 -21
- package/lib/translate/responses.js +69 -29
- package/lib/translate/sse.js +4 -1
- package/package.json +26 -4
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
2
|
+
import { forwardRef, useEffect, useImperativeHandle, useRef, useState, } from 'react';
|
|
3
3
|
import { callSubscriptionsAuth } from './subscriptions-rpc.js';
|
|
4
4
|
/** Providers whose runtime honours a local context-window override. */
|
|
5
5
|
const supportsContext = (provider) => provider === 'codex' || provider === 'claude';
|
|
6
6
|
const border = '0.5px solid var(--dsw-alias-border-l2, #ddd)';
|
|
7
|
-
const actions = {
|
|
7
|
+
const actions = {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
flexWrap: 'wrap',
|
|
10
|
+
gap: 8,
|
|
11
|
+
alignItems: 'center',
|
|
12
|
+
};
|
|
8
13
|
/**
|
|
9
14
|
* Embedded section of the account manager dialog. It owns the model draft
|
|
10
15
|
* (visibility, effort, context, tools) but not its submission: the dialog
|
|
@@ -21,12 +26,19 @@ export const ProviderModelEditor = forwardRef(function ProviderModelEditor({ pro
|
|
|
21
26
|
const [dirty, setDirty] = useState(false);
|
|
22
27
|
const [error, setError] = useState('');
|
|
23
28
|
const generation = useRef(0);
|
|
24
|
-
useEffect(() => () => {
|
|
25
|
-
|
|
29
|
+
useEffect(() => () => {
|
|
30
|
+
generation.current++;
|
|
31
|
+
}, []);
|
|
32
|
+
// Notify only when dirty changes. The parent passes a fresh callback each render.
|
|
33
|
+
/* eslint-disable react-hooks/exhaustive-deps -- onDirtyChange is not a trigger */
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
onDirtyChange?.(dirty);
|
|
36
|
+
}, [dirty]);
|
|
37
|
+
/* eslint-enable react-hooks/exhaustive-deps */
|
|
26
38
|
function reset(data) {
|
|
27
39
|
setCatalog(data);
|
|
28
40
|
setDraft(data.settings);
|
|
29
|
-
setEfforts(Object.fromEntries(data.models.map(model => [model.id, model.configured ?? ''])));
|
|
41
|
+
setEfforts(Object.fromEntries(data.models.map((model) => [model.id, model.configured ?? ''])));
|
|
30
42
|
setContexts(Object.fromEntries(Object.entries(data.settings.contextWindows ?? {}).map(([id, value]) => [id, String(value)])));
|
|
31
43
|
setDirty(false);
|
|
32
44
|
}
|
|
@@ -35,7 +47,9 @@ export const ProviderModelEditor = forwardRef(function ProviderModelEditor({ pro
|
|
|
35
47
|
setBusy(true);
|
|
36
48
|
setError('');
|
|
37
49
|
try {
|
|
38
|
-
const data = await callSubscriptionsAuth(rpc, provider === 'cursor-subscription'
|
|
50
|
+
const data = await callSubscriptionsAuth(rpc, provider === 'cursor-subscription'
|
|
51
|
+
? 'cursorSettings'
|
|
52
|
+
: 'providerSettings', { provider, force });
|
|
39
53
|
if (generation.current === request)
|
|
40
54
|
reset(data);
|
|
41
55
|
}
|
|
@@ -48,8 +62,16 @@ export const ProviderModelEditor = forwardRef(function ProviderModelEditor({ pro
|
|
|
48
62
|
setBusy(false);
|
|
49
63
|
}
|
|
50
64
|
}
|
|
51
|
-
function edit(next) {
|
|
52
|
-
|
|
65
|
+
function edit(next) {
|
|
66
|
+
setDraft(next);
|
|
67
|
+
setDirty(true);
|
|
68
|
+
}
|
|
69
|
+
// `load` is a new function each render; provider and rpc are the triggers.
|
|
70
|
+
/* eslint-disable react-hooks/exhaustive-deps -- avoid refetching every render */
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
void load();
|
|
73
|
+
}, [provider, rpc]);
|
|
74
|
+
/* eslint-enable react-hooks/exhaustive-deps */
|
|
53
75
|
useImperativeHandle(ref, () => ({
|
|
54
76
|
collect() {
|
|
55
77
|
if (!catalog || !dirty)
|
|
@@ -59,47 +81,106 @@ export const ProviderModelEditor = forwardRef(function ProviderModelEditor({ pro
|
|
|
59
81
|
if (!text.trim())
|
|
60
82
|
continue;
|
|
61
83
|
const value = Number(text);
|
|
62
|
-
if (!/^\d+$/.test(text.trim()) ||
|
|
84
|
+
if (!/^\d+$/.test(text.trim()) ||
|
|
85
|
+
!Number.isSafeInteger(value) ||
|
|
86
|
+
value <= 0) {
|
|
63
87
|
setError(t('modelsContextInvalid', { model }));
|
|
64
88
|
return undefined;
|
|
65
89
|
}
|
|
66
90
|
windows[model] = value;
|
|
67
91
|
}
|
|
68
92
|
setError('');
|
|
69
|
-
const { accounts: _accounts, ...settings } = {
|
|
93
|
+
const { accounts: _accounts, ...settings } = {
|
|
94
|
+
...draft,
|
|
95
|
+
...(supportsContext(provider) ? { contextWindows: windows } : {}),
|
|
96
|
+
};
|
|
70
97
|
return {
|
|
71
98
|
settings,
|
|
72
|
-
efforts: catalog.models.flatMap(model => {
|
|
99
|
+
efforts: catalog.models.flatMap((model) => {
|
|
73
100
|
const effort = efforts[model.id] ?? '';
|
|
74
|
-
return effort === (model.configured ?? '') ||
|
|
101
|
+
return effort === (model.configured ?? '') ||
|
|
102
|
+
!model.efforts?.length
|
|
103
|
+
? []
|
|
104
|
+
: [{ model: model.id, effort }];
|
|
75
105
|
}),
|
|
76
106
|
};
|
|
77
107
|
},
|
|
78
|
-
}), [catalog, dirty, draft, contexts, efforts, provider]);
|
|
108
|
+
}), [catalog, dirty, draft, contexts, efforts, provider, t]);
|
|
79
109
|
const allModels = catalog?.models ?? [];
|
|
80
|
-
const known = new Set(allModels.map(model => model.id));
|
|
81
|
-
const missing = (draft.visibleModels ?? [])
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
110
|
+
const known = new Set(allModels.map((model) => model.id));
|
|
111
|
+
const missing = (draft.visibleModels ?? [])
|
|
112
|
+
.filter((id) => !known.has(id))
|
|
113
|
+
.map((id) => ({ id, name: id }));
|
|
114
|
+
const models = [...allModels, ...missing].filter((model) => `${model.name} ${model.id}`
|
|
115
|
+
.toLowerCase()
|
|
116
|
+
.includes(query.trim().toLowerCase()));
|
|
117
|
+
const selected = new Set(draft.visibleModels ?? allModels.map((model) => model.id));
|
|
118
|
+
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'
|
|
119
|
+
? 'cursorManageHint'
|
|
120
|
+
: '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: () => {
|
|
121
|
+
void load(true);
|
|
122
|
+
}, children: t('usageRefresh') }), busy && _jsx("span", { role: "status", children: t('modelDefaultsLoading') })] }), catalog && (_jsxs("fieldset", { disabled: busy || disabled, style: {
|
|
123
|
+
border: 0,
|
|
124
|
+
padding: 0,
|
|
125
|
+
margin: 0,
|
|
126
|
+
minWidth: 0,
|
|
127
|
+
display: 'grid',
|
|
128
|
+
gap: 12,
|
|
129
|
+
}, children: [_jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: draft.visibleModels === undefined, onChange: (event) => {
|
|
85
130
|
const next = { ...draft };
|
|
86
131
|
if (event.target.checked)
|
|
87
132
|
delete next.visibleModels;
|
|
88
133
|
else
|
|
89
|
-
next.visibleModels = allModels.map(model => model.id);
|
|
134
|
+
next.visibleModels = allModels.map((model) => model.id);
|
|
90
135
|
edit(next);
|
|
91
|
-
} }),
|
|
136
|
+
} }), ' ', 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({
|
|
137
|
+
...draft,
|
|
138
|
+
visibleModels: allModels.map((model) => model.id),
|
|
139
|
+
}), children: t('modelsSelectAll') }), _jsx("button", { type: "button", onClick: () => edit({ ...draft, visibleModels: [] }), children: t('modelsSelectNone') })] }), _jsxs("div", { style: {
|
|
140
|
+
maxHeight: 360,
|
|
141
|
+
overflowY: 'auto',
|
|
142
|
+
display: 'grid',
|
|
143
|
+
gap: 8,
|
|
144
|
+
}, children: [models.map((model) => (_jsxs("div", { style: {
|
|
145
|
+
borderBottom: border,
|
|
146
|
+
padding: '8px 2px',
|
|
147
|
+
display: 'grid',
|
|
148
|
+
gap: 8,
|
|
149
|
+
}, children: [_jsxs("label", { style: { overflowWrap: 'anywhere' }, children: [_jsx("input", { type: "checkbox", checked: selected.has(model.id), onChange: (event) => {
|
|
92
150
|
const next = new Set(selected);
|
|
93
151
|
if (event.target.checked)
|
|
94
152
|
next.add(model.id);
|
|
95
153
|
else
|
|
96
154
|
next.delete(model.id);
|
|
97
155
|
edit({ ...draft, visibleModels: [...next] });
|
|
98
|
-
} }),
|
|
99
|
-
setEfforts({
|
|
156
|
+
} }), ' ', 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) => {
|
|
157
|
+
setEfforts({
|
|
158
|
+
...efforts,
|
|
159
|
+
[model.id]: event.target.value,
|
|
160
|
+
});
|
|
100
161
|
setDirty(true);
|
|
101
|
-
}, children: [_jsx("option", { value: "", children: t('modelDefaultsFollowProvider') }), model.configured &&
|
|
102
|
-
_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))
|
|
103
|
-
|
|
104
|
-
|
|
162
|
+
}, children: [_jsx("option", { value: "", children: t('modelDefaultsFollowProvider') }), model.configured &&
|
|
163
|
+
!model.efforts?.some((effort) => effort.id === model.configured) && (_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)))] })] })), supportsContext(provider) &&
|
|
164
|
+
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) => {
|
|
165
|
+
setContexts({
|
|
166
|
+
...contexts,
|
|
167
|
+
[model.id]: event.target.value,
|
|
168
|
+
});
|
|
169
|
+
setDirty(true);
|
|
170
|
+
} })] }), _jsx("small", { children: t('modelsContextBounds', {
|
|
171
|
+
default: model.defaultContextWindow,
|
|
172
|
+
max: model.maxContextWindow,
|
|
173
|
+
}) })] }))] })] }, model.id))), models.length === 0 && (_jsx("span", { children: t('modelDefaultsFilterEmpty', { query }) }))] }), supportsContext(provider) && (_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({
|
|
174
|
+
...draft,
|
|
175
|
+
tools: {
|
|
176
|
+
...draft.tools,
|
|
177
|
+
[tool]: event.target.checked,
|
|
178
|
+
},
|
|
179
|
+
}) }), ' ', t(tool === 'image_generate'
|
|
180
|
+
? 'modelsImage'
|
|
181
|
+
: tool === 'video_generate'
|
|
182
|
+
? 'modelsVideo'
|
|
183
|
+
: tool === 'web_search'
|
|
184
|
+
? 'modelsWebSearch'
|
|
185
|
+
: 'modelsSearch')] }, tool)))] }))] }))] })] }));
|
|
105
186
|
});
|
|
@@ -19,16 +19,28 @@ export interface SpeedSelectState {
|
|
|
19
19
|
* ship it with this shape; it replaces rc.2's `connection.api.sessions.models`
|
|
20
20
|
* read, which the 0.1.2-alpha removed along with the whole `.api` face.
|
|
21
21
|
*/
|
|
22
|
+
/** Selected model pushed by ui-model-selection's directory store. */
|
|
23
|
+
export interface ModelSelectionSnapshot {
|
|
24
|
+
current: {
|
|
25
|
+
provider: string;
|
|
26
|
+
model: string;
|
|
27
|
+
} | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The directory store (`ModelDirectory.store`). Present on hosts that publish
|
|
31
|
+
* selection changes; absent on a directory that only offers `load()`.
|
|
32
|
+
*/
|
|
33
|
+
export interface ModelSelectionStore {
|
|
34
|
+
subscribe(listener: () => void): () => void;
|
|
35
|
+
getSnapshot(): ModelSelectionSnapshot;
|
|
36
|
+
}
|
|
22
37
|
export interface ModelDirectoriesLike {
|
|
23
38
|
/** Resolve one session's shared model directory (throws for unknown sessions). */
|
|
24
39
|
directoryFor(sessionId: string): {
|
|
25
40
|
/** Load the directory; `current` is the session's effective model selection. */
|
|
26
|
-
load(): Promise<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
model: string;
|
|
30
|
-
} | null;
|
|
31
|
-
}>;
|
|
41
|
+
load(): Promise<ModelSelectionSnapshot>;
|
|
42
|
+
/** Pushes selection changes. Missing when the host only offers `load()`. */
|
|
43
|
+
store?: ModelSelectionStore;
|
|
32
44
|
};
|
|
33
45
|
}
|
|
34
46
|
/** Injected dependencies of {@link SpeedSelect} (slot `inject`, session-bound). */
|
|
@@ -37,6 +49,12 @@ export interface SpeedSelectInjected {
|
|
|
37
49
|
loadSpeed: () => Promise<SpeedSelectState>;
|
|
38
50
|
/** Set the session's speed tier; resolves false when the write failed. */
|
|
39
51
|
setSpeed: (tier: SpeedTier) => Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Subscribe to the session's selected model. The listener runs when
|
|
54
|
+
* `provider` or `model` changes, and once when a directory that was missing
|
|
55
|
+
* at subscribe time becomes available. The returned function detaches it.
|
|
56
|
+
*/
|
|
57
|
+
watchModel: (listener: () => void) => () => void;
|
|
40
58
|
}
|
|
41
59
|
/**
|
|
42
60
|
* Props delivered by the slot outlet: the framework session kit and InputZone
|
|
@@ -46,9 +64,10 @@ export interface SpeedSelectInjected {
|
|
|
46
64
|
export type SpeedSelectProps = PropsRuntime<'conversation.input.right'> & Partial<SpeedSelectInjected> & Partial<PropsLocale<'settings.subscriptions'>>;
|
|
47
65
|
/**
|
|
48
66
|
* The `loadSpeed` half of the inject face: the plugin's own speed state plus
|
|
49
|
-
* the host's current model selection (the visibility gate). A
|
|
50
|
-
*
|
|
51
|
-
*
|
|
67
|
+
* the host's current model selection (the visibility gate). A session whose
|
|
68
|
+
* model selection is unavailable (an addressed subagent) answers hidden.
|
|
69
|
+
* Any other model-directory failure throws, so the caller keeps its last
|
|
70
|
+
* known state instead of locking the toggle away.
|
|
52
71
|
*
|
|
53
72
|
* `sessionId` is a plain string: slot and command contexts brand it through
|
|
54
73
|
* different dsh-session copies, and only the service boundary needs one.
|
|
@@ -58,14 +77,43 @@ export type SpeedSelectProps = PropsRuntime<'conversation.input.right'> & Partia
|
|
|
58
77
|
* at all) simply keeps the toggle hidden.
|
|
59
78
|
*/
|
|
60
79
|
export declare function createSpeedLoader(connection: ConnectionHandle, models: () => ModelDirectoriesLike | undefined, sessionId: string): SpeedSelectInjected['loadSpeed'];
|
|
80
|
+
/** Stable identity of a model selection. Empty when nothing is selected. */
|
|
81
|
+
export declare function modelSelectionKey(current: ModelSelectionSnapshot['current'] | undefined): string;
|
|
82
|
+
/**
|
|
83
|
+
* How often a host without a directory store is re-read, and how often a
|
|
84
|
+
* missing directory service is retried. Neither interval calls
|
|
85
|
+
* `subscriptions-auth.speed`.
|
|
86
|
+
*/
|
|
87
|
+
export declare const MODEL_DIRECTORY_POLL_INTERVAL_MS = 3000;
|
|
88
|
+
/**
|
|
89
|
+
* Mount reads of `speed`, including the first attempt. Further failures stop
|
|
90
|
+
* instead of polling for the life of the composer.
|
|
91
|
+
*/
|
|
92
|
+
export declare const SPEED_MOUNT_READ_ATTEMPTS = 4;
|
|
93
|
+
/** Fired after `/fast` writes a tier, so an open composer re-reads `speed`. */
|
|
94
|
+
export declare const SPEED_CHANGED_EVENT = "dsh:subscriptions:speed-changed";
|
|
95
|
+
/** Tell mounted Speed controls that this page changed a session tier. */
|
|
96
|
+
export declare function notifySpeedChanged(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Subscribe to the session's selected model. A directory store notifies the
|
|
99
|
+
* listener only when `provider` or `model` changes. A directory with no store
|
|
100
|
+
* is re-read on {@link MODEL_DIRECTORY_POLL_INTERVAL_MS}; a service that is
|
|
101
|
+
* not registered yet, or whose `directoryFor` throws, is retried on that same
|
|
102
|
+
* interval. The first successful attach after a miss notifies once, so a
|
|
103
|
+
* mount that ran before the service existed reads `speed` again.
|
|
104
|
+
*/
|
|
105
|
+
export declare function createModelSelectionWatch(models: () => ModelDirectoriesLike | undefined, sessionId: string): SpeedSelectInjected['watchModel'];
|
|
61
106
|
/** The `setSpeed` half of the inject face: boolean outcome for the component's busy state. */
|
|
62
107
|
export declare function createSpeedSetter(connection: ConnectionHandle, sessionId: string): SpeedSelectInjected['setSpeed'];
|
|
63
108
|
/**
|
|
64
109
|
* The composer Speed control: a trigger reading `速度 · 快速`/`速度 · 标准`
|
|
65
110
|
* that opens a two-row menu (standard/fast with descriptions, check mark on
|
|
66
|
-
* the current tier).
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
111
|
+
* the current tier). It reads `subscriptions-auth.speed` on mount, when the
|
|
112
|
+
* menu opens, when {@link SpeedSelectInjected.watchModel} reports a new
|
|
113
|
+
* selected model, and when {@link notifySpeedChanged} fires. Until the first
|
|
114
|
+
* read succeeds, a failure is retried on
|
|
115
|
+
* {@link MODEL_DIRECTORY_POLL_INTERVAL_MS}, at most
|
|
116
|
+
* {@link SPEED_MOUNT_READ_ATTEMPTS} times; after that, a failed read keeps
|
|
117
|
+
* the last known state.
|
|
70
118
|
*/
|
|
71
|
-
export declare function SpeedSelect({ loadSpeed, setSpeed, t }: SpeedSelectProps): import("react").JSX.Element | null;
|
|
119
|
+
export declare function SpeedSelect({ loadSpeed, setSpeed, watchModel, t, }: SpeedSelectProps): import("react").JSX.Element | null;
|