dsh-subscriptions 0.1.5 → 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 -154
- 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.d.ts +73 -2
- package/lib/auth/rpc.js +124 -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 +13 -0
- package/lib/client/OllamaCard.js +94 -0
- package/lib/client/OllamaSettingsManager.d.ts +24 -0
- package/lib/client/OllamaSettingsManager.js +329 -0
- package/lib/client/ProviderAccountManager.d.ts +1 -1
- package/lib/client/ProviderAccountManager.js +164 -49
- package/lib/client/ProviderModelEditor.js +109 -26
- package/lib/client/SpeedSelect.d.ts +62 -14
- package/lib/client/SpeedSelect.js +257 -46
- package/lib/client/SubscriptionUsageBadge.d.ts +5 -11
- package/lib/client/SubscriptionUsageBadge.js +301 -112
- package/lib/client/SubscriptionsSection.d.ts +2 -0
- package/lib/client/SubscriptionsSection.js +259 -85
- package/lib/client/UsageBadgeDisplaySetting.js +35 -12
- package/lib/client/UsageMeter.d.ts +1 -1
- package/lib/client/UsageMeter.js +69 -27
- 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 +78 -0
- package/lib/client/locales.js +121 -34
- package/lib/client/ollama-draft.d.ts +229 -0
- package/lib/client/ollama-draft.js +255 -0
- 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.d.ts +7 -0
- package/lib/client/usage-pace.js +43 -10
- package/lib/client.js +1647 -266
- package/lib/client.js.map +1 -1
- package/lib/http.js +1 -1
- package/lib/index.d.ts +28 -3
- package/lib/index.js +9329 -8217
- package/lib/model-defaults.js +4 -2
- package/lib/provider-settings.d.ts +14 -1
- package/lib/provider-settings.js +64 -20
- 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 +23 -3
- package/lib/providers/claude.js +167 -92
- 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.d.ts +14 -0
- package/lib/providers/common.js +118 -38
- 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.d.ts +9 -2
- package/lib/providers/external-usage-controller.js +30 -7
- package/lib/providers/external-usage.d.ts +8 -0
- package/lib/providers/external-usage.js +140 -20
- 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.d.ts +90 -0
- package/lib/providers/ollama-settings.js +213 -0
- package/lib/providers/ollama-web.d.ts +46 -0
- package/lib/providers/ollama-web.js +231 -0
- package/lib/providers/ollama.d.ts +107 -0
- package/lib/providers/ollama.js +608 -0
- 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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ConnectionHandle } from '@deepseek-ai/dsh-api-remotes/client';
|
|
2
|
+
import type { SubscriptionsSectionInjected } from './SubscriptionsSection.js';
|
|
3
|
+
type Translate = SubscriptionsSectionInjected['t'];
|
|
4
|
+
interface Props {
|
|
5
|
+
rpc: ConnectionHandle['rpc'];
|
|
6
|
+
t: Translate;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
/** Called after a successful save or reset, so the card re-reads its status. */
|
|
9
|
+
onSaved: () => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ollama Cloud settings dialog. It owns one draft (model list, web toggle,
|
|
13
|
+
* base URL and credential reference) that Save writes in a single
|
|
14
|
+
* `ollamaSetSettings` call, so a failure keeps every edit. Fetching the cloud
|
|
15
|
+
* catalog is a read-only side trip, and a key typed for the fetch never
|
|
16
|
+
* leaves this component. The model list follows the shared model editor: a
|
|
17
|
+
* filter, select all/none over the filtered rows, and one checkbox per
|
|
18
|
+
* model, where ticking edits the draft and enables Save. Ollama adds what the
|
|
19
|
+
* shared editor lacks: a display name, ordering, and a local context window.
|
|
20
|
+
* Unticking keeps the row's full settings in a dialog-local stash, so ticking
|
|
21
|
+
* it again restores them even when the cloud listing no longer returns it.
|
|
22
|
+
*/
|
|
23
|
+
export declare function OllamaSettingsManager({ rpc, t, onClose, onSaved }: Props): import("react").JSX.Element;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useId, useRef, useState } from 'react';
|
|
3
|
+
import { callSubscriptionsAuth } from './subscriptions-rpc.js';
|
|
4
|
+
import { contextLabel, effortOptions, moveModel, parseContextInput, renameModel, setModelContext, setModelEffort, tickModel, tickModels, untickModel, untickModels, } from './ollama-draft.js';
|
|
5
|
+
import { subscriptionCardStyles as styles } from './subscription-card-styles.js';
|
|
6
|
+
import { providerSettingsCss } from './provider-settings-styles.js';
|
|
7
|
+
const border = '0.5px solid var(--dsw-alias-border-l2)';
|
|
8
|
+
const stack = { display: 'grid', gap: 12, minWidth: 0 };
|
|
9
|
+
const actions = {
|
|
10
|
+
display: 'flex',
|
|
11
|
+
flexWrap: 'wrap',
|
|
12
|
+
gap: 8,
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
};
|
|
15
|
+
function message(error) {
|
|
16
|
+
return error instanceof Error ? error.message : String(error);
|
|
17
|
+
}
|
|
18
|
+
/** `vision · thinking · context 262K`, dropping whatever the model does not advertise. */
|
|
19
|
+
function capabilities(t, model) {
|
|
20
|
+
const context = contextLabel(model.contextWindow);
|
|
21
|
+
return [
|
|
22
|
+
model.vision === true ? t('ollamaCapVision') : false,
|
|
23
|
+
model.thinking === true ? t('ollamaCapThinking') : false,
|
|
24
|
+
context === undefined ? false : t('ollamaContext', { tokens: context }),
|
|
25
|
+
]
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.join(' · ');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Ollama Cloud settings dialog. It owns one draft (model list, web toggle,
|
|
31
|
+
* base URL and credential reference) that Save writes in a single
|
|
32
|
+
* `ollamaSetSettings` call, so a failure keeps every edit. Fetching the cloud
|
|
33
|
+
* catalog is a read-only side trip, and a key typed for the fetch never
|
|
34
|
+
* leaves this component. The model list follows the shared model editor: a
|
|
35
|
+
* filter, select all/none over the filtered rows, and one checkbox per
|
|
36
|
+
* model, where ticking edits the draft and enables Save. Ollama adds what the
|
|
37
|
+
* shared editor lacks: a display name, ordering, and a local context window.
|
|
38
|
+
* Unticking keeps the row's full settings in a dialog-local stash, so ticking
|
|
39
|
+
* it again restores them even when the cloud listing no longer returns it.
|
|
40
|
+
*/
|
|
41
|
+
export function OllamaSettingsManager({ rpc, t, onClose, onSaved }) {
|
|
42
|
+
const dialog = useRef(null);
|
|
43
|
+
const title = useId();
|
|
44
|
+
const description = useId();
|
|
45
|
+
const [view, setView] = useState();
|
|
46
|
+
const [draft, setDraft] = useState({});
|
|
47
|
+
const [dirty, setDirty] = useState(false);
|
|
48
|
+
const [loading, setLoading] = useState(true);
|
|
49
|
+
const [saving, setSaving] = useState(false);
|
|
50
|
+
const [error, setError] = useState('');
|
|
51
|
+
const [saveError, setSaveError] = useState('');
|
|
52
|
+
const [attempt, setAttempt] = useState(0);
|
|
53
|
+
const [apiKey, setApiKey] = useState('');
|
|
54
|
+
const [candidates, setCandidates] = useState();
|
|
55
|
+
const [fetching, setFetching] = useState(false);
|
|
56
|
+
const [fetchError, setFetchError] = useState('');
|
|
57
|
+
const [query, setQuery] = useState('');
|
|
58
|
+
const [expanded, setExpanded] = useState(new Set());
|
|
59
|
+
const [stash, setStash] = useState(new Map());
|
|
60
|
+
const [contextText, setContextText] = useState({});
|
|
61
|
+
const alive = useRef(true);
|
|
62
|
+
const saveLock = useRef(false);
|
|
63
|
+
const fetchLock = useRef(false);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
alive.current = true;
|
|
66
|
+
const element = dialog.current;
|
|
67
|
+
const previous = document.activeElement;
|
|
68
|
+
element.showModal();
|
|
69
|
+
return () => {
|
|
70
|
+
alive.current = false;
|
|
71
|
+
element.close();
|
|
72
|
+
if (previous instanceof HTMLElement && previous.isConnected)
|
|
73
|
+
previous.focus();
|
|
74
|
+
};
|
|
75
|
+
}, []);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
let current = true;
|
|
78
|
+
setLoading(true);
|
|
79
|
+
setError('');
|
|
80
|
+
void callSubscriptionsAuth(rpc, 'ollamaSettings', {})
|
|
81
|
+
.then((data) => {
|
|
82
|
+
if (!current)
|
|
83
|
+
return;
|
|
84
|
+
setView(data);
|
|
85
|
+
// An unset store value inherits the deployed config: the checkbox
|
|
86
|
+
// shows the effective state, and ticking it writes the override.
|
|
87
|
+
setDraft({ ...data.settings });
|
|
88
|
+
setStash(new Map());
|
|
89
|
+
setContextText({});
|
|
90
|
+
setDirty(false);
|
|
91
|
+
})
|
|
92
|
+
.catch((failure) => {
|
|
93
|
+
if (current)
|
|
94
|
+
setError(t('ollamaModelsLoadFailed', { message: message(failure) }));
|
|
95
|
+
})
|
|
96
|
+
.finally(() => {
|
|
97
|
+
if (current)
|
|
98
|
+
setLoading(false);
|
|
99
|
+
});
|
|
100
|
+
return () => {
|
|
101
|
+
current = false;
|
|
102
|
+
};
|
|
103
|
+
// `t` only formats the load error. A new translator must not refetch.
|
|
104
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- refetch on rpc and attempt only
|
|
105
|
+
}, [rpc, attempt]);
|
|
106
|
+
function edit(next) {
|
|
107
|
+
setDraft(next);
|
|
108
|
+
setDirty(true);
|
|
109
|
+
}
|
|
110
|
+
/** Fetch the cloud catalog; a failure keeps the previous list and the draft. */
|
|
111
|
+
async function fetchCandidates() {
|
|
112
|
+
if (fetchLock.current)
|
|
113
|
+
return;
|
|
114
|
+
fetchLock.current = true;
|
|
115
|
+
setFetching(true);
|
|
116
|
+
setFetchError('');
|
|
117
|
+
try {
|
|
118
|
+
const value = await callSubscriptionsAuth(rpc, 'ollamaModels', {
|
|
119
|
+
...(apiKey ? { apiKey } : {}),
|
|
120
|
+
...(draft.baseURL ? { baseURL: draft.baseURL } : {}),
|
|
121
|
+
});
|
|
122
|
+
if (!alive.current)
|
|
123
|
+
return;
|
|
124
|
+
setCandidates(value.models);
|
|
125
|
+
}
|
|
126
|
+
catch (failure) {
|
|
127
|
+
if (alive.current)
|
|
128
|
+
setFetchError(t('ollamaFetchFailed', { message: message(failure) }));
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
fetchLock.current = false;
|
|
132
|
+
if (alive.current)
|
|
133
|
+
setFetching(false);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Save the whole draft; a failure keeps the dialog open with every edit. */
|
|
137
|
+
async function save() {
|
|
138
|
+
if (saveLock.current)
|
|
139
|
+
return;
|
|
140
|
+
saveLock.current = true;
|
|
141
|
+
setSaving(true);
|
|
142
|
+
setSaveError('');
|
|
143
|
+
try {
|
|
144
|
+
await callSubscriptionsAuth(rpc, 'ollamaSetSettings', { settings: draft });
|
|
145
|
+
if (alive.current) {
|
|
146
|
+
onSaved();
|
|
147
|
+
onClose();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (failure) {
|
|
151
|
+
if (alive.current)
|
|
152
|
+
setSaveError(t('ollamaModelsSaveFailed', { message: message(failure) }));
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
saveLock.current = false;
|
|
156
|
+
if (alive.current)
|
|
157
|
+
setSaving(false);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Drop every stored override, then reload the draft from the deployment values. */
|
|
161
|
+
async function resetDefaults() {
|
|
162
|
+
if (saveLock.current)
|
|
163
|
+
return;
|
|
164
|
+
if (!window.confirm(t('ollamaResetConfirm')))
|
|
165
|
+
return;
|
|
166
|
+
saveLock.current = true;
|
|
167
|
+
setSaving(true);
|
|
168
|
+
setSaveError('');
|
|
169
|
+
try {
|
|
170
|
+
await callSubscriptionsAuth(rpc, 'ollamaSetSettings', { settings: {} });
|
|
171
|
+
if (alive.current) {
|
|
172
|
+
setAttempt((value) => value + 1);
|
|
173
|
+
onSaved();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (failure) {
|
|
177
|
+
if (alive.current)
|
|
178
|
+
setSaveError(t('ollamaModelsSaveFailed', { message: message(failure) }));
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
saveLock.current = false;
|
|
182
|
+
if (alive.current)
|
|
183
|
+
setSaving(false);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function editOverride(field, value) {
|
|
187
|
+
const next = { ...draft };
|
|
188
|
+
if (value.trim())
|
|
189
|
+
next[field] = value;
|
|
190
|
+
else
|
|
191
|
+
delete next[field];
|
|
192
|
+
edit(next);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* One list for both sources, like the shared editor: the ticked models in
|
|
196
|
+
* draft order first (so Move up/down is visible), then the unticked ones
|
|
197
|
+
* (stashed in this dialog, or fetched and not yet adopted). A kept model
|
|
198
|
+
* the fetch did not return stays listed, ticked or not.
|
|
199
|
+
*/
|
|
200
|
+
const fetchedById = new Map((candidates ?? []).map((candidate) => [candidate.id, candidate]));
|
|
201
|
+
const present = new Set((draft.models ?? []).map((model) => model.id));
|
|
202
|
+
const asRow = (model, ticked) => {
|
|
203
|
+
const fetched = fetchedById.get(model.id);
|
|
204
|
+
// The latest fetch outranks the stored snapshot, matching the runtime:
|
|
205
|
+
// discovery is the ceiling and the snapshot only stands in without it.
|
|
206
|
+
const contextWindow = fetched?.contextWindow ?? model.contextWindow;
|
|
207
|
+
return {
|
|
208
|
+
id: model.id,
|
|
209
|
+
name: model.name ?? fetched?.name ?? model.id,
|
|
210
|
+
ticked,
|
|
211
|
+
vision: model.vision === true || fetched?.vision === true,
|
|
212
|
+
thinking: model.thinking === true || fetched?.thinking === true,
|
|
213
|
+
...(contextWindow === undefined ? {} : { contextWindow }),
|
|
214
|
+
efforts: model.efforts ?? fetched?.efforts ?? [],
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
const rows = [
|
|
218
|
+
...(draft.models ?? []).map((model) => asRow(model, true)),
|
|
219
|
+
...[...stash.values()]
|
|
220
|
+
.filter((model) => !present.has(model.id))
|
|
221
|
+
.map((model) => asRow(model, false)),
|
|
222
|
+
...(candidates ?? [])
|
|
223
|
+
.filter((candidate) => !present.has(candidate.id) && !stash.has(candidate.id))
|
|
224
|
+
.map((candidate) => asRow({ id: candidate.id }, false)),
|
|
225
|
+
];
|
|
226
|
+
const shown = rows.filter((row) => `${row.name} ${row.id}`.toLowerCase().includes(query.trim().toLowerCase()));
|
|
227
|
+
/** Rename and default-effort edits ride the tested draft helpers. */
|
|
228
|
+
function rename(id, name) {
|
|
229
|
+
edit({ ...draft, models: renameModel(draft.models ?? [], id, name) });
|
|
230
|
+
}
|
|
231
|
+
function setEffort(id, effort) {
|
|
232
|
+
edit({ ...draft, models: setModelEffort(draft.models ?? [], id, effort) });
|
|
233
|
+
}
|
|
234
|
+
/** Keep the typed text; only a valid number (or blank) reaches the draft. */
|
|
235
|
+
function setContext(id, text) {
|
|
236
|
+
setContextText((current) => ({ ...current, [id]: text }));
|
|
237
|
+
const tokens = parseContextInput(text);
|
|
238
|
+
if (tokens !== null)
|
|
239
|
+
edit({
|
|
240
|
+
...draft,
|
|
241
|
+
models: setModelContext(draft.models ?? [], id, tokens),
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function applyTicks(next) {
|
|
245
|
+
setStash(next.stash);
|
|
246
|
+
edit({ ...draft, models: next.models });
|
|
247
|
+
}
|
|
248
|
+
const invalidContext = Object.entries(contextText)
|
|
249
|
+
.filter(([id, text]) => present.has(id) && parseContextInput(text) === null)
|
|
250
|
+
.map(([id]) => id);
|
|
251
|
+
return (_jsxs("dialog", { className: "dsh-subscription-manager", ref: dialog, "aria-labelledby": title, "aria-describedby": description, onCancel: (event) => {
|
|
252
|
+
if (saveLock.current)
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
}, onClose: onClose, style: {
|
|
255
|
+
width: 620,
|
|
256
|
+
maxWidth: 'calc(100vw - 32px)',
|
|
257
|
+
maxHeight: 'calc(100dvh - 32px)',
|
|
258
|
+
overflow: 'auto',
|
|
259
|
+
}, 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('ollamaManageTitle') }), _jsx("button", { type: "button", autoFocus: true, disabled: saving, onClick: onClose, children: t('imageClose') })] }), _jsx("p", { id: description, className: "dsh-subscription-hint", children: t('ollamaManageHint') }), view?.configOverridesModels === true && (_jsx("p", { className: "dsh-subscription-hint", children: t('ollamaCatalogOverride') })), error && _jsx("p", { role: "alert", children: error }), loading && (_jsx("p", { role: "status", className: "dsh-subscription-hint", children: t('modelDefaultsLoading') })), !loading && !view && (_jsx("button", { type: "button", onClick: () => setAttempt((value) => value + 1), children: t('modelDefaultsRetry') })), view && (_jsxs("fieldset", { disabled: saving, style: { ...stack, border: 0, margin: 0, padding: 0, minWidth: 0 }, children: [_jsxs("div", { style: {
|
|
260
|
+
borderTop: border,
|
|
261
|
+
paddingTop: 12,
|
|
262
|
+
display: 'grid',
|
|
263
|
+
gap: 12,
|
|
264
|
+
}, children: [_jsx("h3", { style: { margin: 0 }, children: t('modelsEdit') }), _jsxs("div", { style: actions, children: [_jsx("input", { type: "password", autoComplete: "off", style: { flex: '1 1 180px' }, "aria-label": t('ollamaKeyPlaceholder'), placeholder: t('ollamaKeyPlaceholder'), value: apiKey, onChange: (event) => setApiKey(event.target.value) }), _jsx("button", { type: "button", className: "dsh-subscription-quiet", disabled: fetching, onClick: () => {
|
|
265
|
+
void fetchCandidates();
|
|
266
|
+
}, children: fetching ? t('ollamaFetching') : t('ollamaFetch') }), candidates !== undefined && (_jsx("span", { className: "dsh-subscription-hint", children: t('ollamaCandidatesCount', { count: candidates.length }) }))] }), _jsx("p", { className: "dsh-subscription-hint", children: t('ollamaKeyHint') }), fetchError && _jsx("p", { role: "alert", children: fetchError }), candidates?.length === 0 && (_jsx("p", { className: "dsh-subscription-hint", children: t('ollamaCandidatesEmpty') })), _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: () => applyTicks(tickModels(draft.models ?? [], stash, candidates ?? [], shown.map((row) => row.id))), children: t('modelsSelectAll') }), _jsx("button", { type: "button", onClick: () => applyTicks(untickModels(draft.models ?? [], stash, shown.map((row) => row.id))), children: t('modelsSelectNone') })] }), _jsxs("div", { style: {
|
|
267
|
+
maxHeight: 360,
|
|
268
|
+
overflowY: 'auto',
|
|
269
|
+
display: 'grid',
|
|
270
|
+
gap: 8,
|
|
271
|
+
}, children: [shown.map((row) => {
|
|
272
|
+
const stored = (draft.models ?? []).find((entry) => entry.id === row.id);
|
|
273
|
+
const index = (draft.models ?? []).findIndex((entry) => entry.id === row.id);
|
|
274
|
+
const open = expanded.has(row.id);
|
|
275
|
+
const details = `${row.id}-details`;
|
|
276
|
+
const efforts = stored === undefined
|
|
277
|
+
? []
|
|
278
|
+
: effortOptions(stored, fetchedById.get(row.id)?.efforts, view.models.find((entry) => entry.id === row.id)
|
|
279
|
+
?.efforts);
|
|
280
|
+
const contextProblem = invalidContext.includes(row.id);
|
|
281
|
+
return (_jsxs("div", { style: {
|
|
282
|
+
borderBottom: border,
|
|
283
|
+
padding: '8px 2px',
|
|
284
|
+
display: 'grid',
|
|
285
|
+
gap: 8,
|
|
286
|
+
}, children: [_jsxs("label", { style: { overflowWrap: 'anywhere' }, children: [_jsx("input", { type: "checkbox", checked: row.ticked, onChange: (event) => {
|
|
287
|
+
applyTicks(event.target.checked
|
|
288
|
+
? tickModel(draft.models ?? [], stash, candidates ?? [], row.id)
|
|
289
|
+
: untickModel(draft.models ?? [], stash, row.id));
|
|
290
|
+
} }), ' ', row.name, ' ', _jsx("span", { style: styles.status, children: capabilities(t, row) })] }), stored !== undefined && (_jsxs("div", { style: actions, children: [row.thinking && efforts.length > 0 && (_jsxs("label", { style: actions, children: [t('modelDefaultsTitle'), _jsxs("select", { "aria-label": `${row.name} ${t('modelDefaultsTitle')}`, value: stored.defaultEffort ?? '', onChange: (event) => setEffort(row.id, event.target.value), children: [_jsx("option", { value: "", children: t('modelDefaultsFollowProvider') }), efforts.map((effort) => (_jsx("option", { value: effort.id, disabled: effort.unavailable === true, children: effort.unavailable === true
|
|
291
|
+
? `${effort.name} (${t('modelsUnavailable')})`
|
|
292
|
+
: effort.name }, effort.id)))] })] })), row.thinking && efforts.length === 0 && (_jsx("small", { children: t('ollamaEffortsUnknown') })), _jsxs("label", { style: actions, children: [t('modelsContext'), _jsx("input", { style: { width: 140 }, inputMode: "numeric", "aria-invalid": contextProblem, value: contextText[row.id] ??
|
|
293
|
+
(stored.contextOverride === undefined
|
|
294
|
+
? ''
|
|
295
|
+
: String(stored.contextOverride)), "aria-label": `${row.name} ${t('modelsContext')}`, placeholder: row.contextWindow === undefined
|
|
296
|
+
? ''
|
|
297
|
+
: String(row.contextWindow), onChange: (event) => setContext(row.id, event.target.value) })] }), row.contextWindow !== undefined && (_jsx("small", { children: t('modelsContextBounds', {
|
|
298
|
+
default: row.contextWindow,
|
|
299
|
+
max: row.contextWindow,
|
|
300
|
+
}) })), _jsxs("button", { type: "button", className: "dsh-subscription-quiet", "aria-expanded": open, "aria-controls": details, "aria-label": `${row.name} ${t('ollamaRowDetails')}`, onClick: () => {
|
|
301
|
+
const next = new Set(expanded);
|
|
302
|
+
if (open)
|
|
303
|
+
next.delete(row.id);
|
|
304
|
+
else
|
|
305
|
+
next.add(row.id);
|
|
306
|
+
setExpanded(next);
|
|
307
|
+
}, children: [t('ollamaRowDetails'), " ", open ? '\u25BE' : '\u25B8'] })] })), contextProblem && (_jsx("p", { role: "alert", children: t('modelsContextInvalid', { model: row.name }) })), stored !== undefined && open && (_jsxs("div", { id: details, style: actions, children: [_jsxs("label", { style: actions, children: [t('ollamaDisplayName'), _jsx("input", { value: stored.name ?? '', placeholder: row.id, "aria-label": `${row.name} ${t('ollamaDisplayName')}`, onChange: (event) => rename(row.id, event.target.value), onBlur: (event) => rename(row.id, event.target.value.trim()) })] }), _jsx("button", { type: "button", disabled: index === 0, "aria-label": `${row.name} ${t('ollamaMoveUp')}`, onClick: () => edit({
|
|
308
|
+
...draft,
|
|
309
|
+
models: moveModel(draft.models ?? [], row.id, -1),
|
|
310
|
+
}), children: t('ollamaMoveUp') }), _jsx("button", { type: "button", disabled: index === (draft.models ?? []).length - 1, "aria-label": `${row.name} ${t('ollamaMoveDown')}`, onClick: () => edit({
|
|
311
|
+
...draft,
|
|
312
|
+
models: moveModel(draft.models ?? [], row.id, 1),
|
|
313
|
+
}), children: t('ollamaMoveDown') })] }))] }, row.id));
|
|
314
|
+
}), shown.length === 0 && (_jsx("span", { className: "dsh-subscription-hint", children: query.trim()
|
|
315
|
+
? t('modelDefaultsFilterEmpty', { query })
|
|
316
|
+
: t('ollamaModelsEmpty') }))] }), _jsx("small", { children: t('modelsContextHint') })] }), _jsxs("label", { style: { ...stack, gap: 6 }, children: [_jsx("span", { className: "dsh-subscription-label", children: t('ollamaBaseURL') }), _jsx("input", { value: draft.baseURL ?? '', placeholder: view.effective.baseURL, onChange: (event) => editOverride('baseURL', event.target.value) })] }), _jsxs("label", { style: { ...stack, gap: 6 }, children: [_jsx("span", { className: "dsh-subscription-label", children: t('ollamaApiKeyRef') }), _jsx("input", { value: draft.apiKeyRef ?? '', placeholder: view.effective.apiKeyRef, onChange: (event) => editOverride('apiKeyRef', event.target.value) })] }), _jsx("p", { className: "dsh-subscription-hint", children: t('ollamaConnectionHint') }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: (draft.web ?? view.effective.web) === true, onChange: (event) => edit({ ...draft, web: event.target.checked }) }), ' ', t('modelsWebSearch')] }), _jsx("p", { className: "dsh-subscription-hint", children: t('ollamaWebHint') })] })), _jsxs("footer", { style: {
|
|
317
|
+
...stack,
|
|
318
|
+
gap: 8,
|
|
319
|
+
borderTop: border,
|
|
320
|
+
padding: '14px 0 8px',
|
|
321
|
+
position: 'sticky',
|
|
322
|
+
bottom: 0,
|
|
323
|
+
background: 'var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1))',
|
|
324
|
+
}, children: [saveError && _jsx("p", { role: "alert", children: saveError }), _jsxs("div", { style: { ...actions, justifyContent: 'flex-end' }, children: [_jsx("button", { type: "button", style: { marginRight: 'auto' }, disabled: loading || saving, onClick: () => {
|
|
325
|
+
void resetDefaults();
|
|
326
|
+
}, children: t('ollamaResetDefaults') }), _jsx("button", { type: "button", disabled: saving, onClick: onClose, children: t('cancel') }), _jsx("button", { type: "button", className: "dsh-subscription-primary", disabled: loading || saving || !dirty || invalidContext.length > 0, onClick: () => {
|
|
327
|
+
void save();
|
|
328
|
+
}, children: saving ? t('modelDefaultsSaving') : t('modelsSave') })] })] })] })] }));
|
|
329
|
+
}
|
|
@@ -9,5 +9,5 @@ interface Props {
|
|
|
9
9
|
onClose: () => void;
|
|
10
10
|
}
|
|
11
11
|
/** Native top-layer dialog provides keyboard containment, Escape and focus restoration. */
|
|
12
|
-
export declare function ProviderAccountManager({ provider, name, rpc, t, onClose }: Props): import("react").JSX.Element;
|
|
12
|
+
export declare function ProviderAccountManager({ provider, name, rpc, t, onClose, }: Props): import("react").JSX.Element;
|
|
13
13
|
export {};
|