@adecore/agents-react 0.37.0 → 0.37.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/dist/agents/provider-paths.js +3 -1
- package/dist/chat/logic/picker-entries.d.ts +6 -1
- package/dist/chat/logic/picker-entries.js +10 -0
- package/dist/chat/ui/Pickers.js +151 -207
- package/dist/chat/ui/RunSettings.js +25 -21
- package/dist/providers/parts.js +2 -1
- package/dist/theme.css +5 -1
- package/dist/usage/format.js +4 -2
- package/package.json +8 -8
- package/src/agents/provider-paths.ts +5 -1
- package/src/chat/logic/picker-entries.ts +12 -1
- package/src/chat/ui/Pickers.tsx +8 -2
- package/src/chat/ui/RunSettings.tsx +29 -23
- package/src/providers/parts.tsx +2 -1
- package/src/theme.css +5 -1
- package/src/usage/format.ts +4 -2
|
@@ -3,8 +3,10 @@ import { siGithubcopilot } from 'simple-icons';
|
|
|
3
3
|
* The marks of Anthropic, OpenAI, xAI and GitHub Copilot, and a monogram for a provider with no mark of its own. Lucide has no brand marks, so these are the icon rule's
|
|
4
4
|
* exception for provider marks. One path each, in `currentColor`, so a row decides how loud the logo is.
|
|
5
5
|
*/
|
|
6
|
+
const CLAUDE_PATH = 'M4.709 15.955l4.72-2.647.079-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.377-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.048.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.607.212-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.914-1.316-.012.01z';
|
|
6
7
|
export const PROVIDER_PATHS = {
|
|
7
|
-
claude:
|
|
8
|
+
claude: CLAUDE_PATH,
|
|
9
|
+
'anthropic-claude-api': CLAUDE_PATH,
|
|
8
10
|
codex: 'M21.55 10.004a5.416 5.416 0 00-.478-4.501c-1.217-2.09-3.662-3.166-6.05-2.66A5.59 5.59 0 0010.831 1C8.39.995 6.224 2.546 5.473 4.838A5.553 5.553 0 001.76 7.496a5.487 5.487 0 00.691 6.5 5.416 5.416 0 00.477 4.502c1.217 2.09 3.662 3.165 6.05 2.66A5.586 5.586 0 0013.168 23c2.443.006 4.61-1.546 5.361-3.84a5.554 5.554 0 003.715-2.66 5.488 5.488 0 00-.693-6.497v.001zm-8.381 11.558a4.199 4.199 0 01-2.675-.954c.034-.018.093-.05.132-.074l4.44-2.53a.71.71 0 00.364-.623v-6.176l1.877 1.069c.02.01.033.029.036.05v5.115c-.003 2.274-1.87 4.118-4.174 4.123zM4.192 17.78a4.059 4.059 0 01-.498-2.763c.032.019.09.055.131.078l4.44 2.53c.225.13.504.13.73 0l5.42-3.088v2.138a.068.068 0 01-.027.057L9.9 19.288c-1.999 1.136-4.552.46-5.707-1.51h-.001zM3.023 8.216A4.15 4.15 0 015.198 6.41l-.002.151v5.06a.711.711 0 00.364.624l5.42 3.087-1.876 1.07a.067.067 0 01-.063.005l-4.489-2.559c-1.995-1.14-2.679-3.658-1.53-5.63h.001zm15.417 3.54l-5.42-3.088L14.896 7.6a.067.067 0 01.063-.006l4.489 2.557c1.998 1.14 2.683 3.662 1.529 5.633a4.163 4.163 0 01-2.174 1.807V12.38a.71.71 0 00-.363-.623zm1.867-2.773a6.04 6.04 0 00-.132-.078l-4.44-2.53a.731.731 0 00-.729 0l-5.42 3.088V7.325a.068.068 0 01.027-.057L14.1 4.713c2-1.137 4.555-.46 5.707 1.513.487.833.664 1.809.499 2.757h.001zm-11.741 3.81l-1.877-1.068a.065.065 0 01-.036-.051V6.559c.001-2.277 1.873-4.122 4.181-4.12.976 0 1.92.338 2.671.954-.034.018-.092.05-.131.073l-4.44 2.53a.71.71 0 00-.365.623l-.003 6.173v.001zm1.02-2.168L12 9.25l2.414 1.375v2.75L12 14.75l-2.415-1.375v-2.75z',
|
|
9
11
|
nanogpt: 'M5 20V4h2.6l8.8 11.2V4H19v16h-2.6L7.6 8.8V20z',
|
|
10
12
|
grok: 'M6.469 8.776 16.512 23h-4.464L2.005 8.776H6.47Zm-.004 7.9 2.233 3.164L6.467 23H2l4.465-6.324ZM22 2.582V23h-3.659V7.764L22 2.582ZM22 1l-9.952 14.095-2.233-3.163L17.533 1H22Z',
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AgentKind, type ModelInfo, type ProviderInfo } from '@adecore/agent-contracts';
|
|
2
|
+
export declare function inPickerOrder<T extends {
|
|
3
|
+
kind: AgentKind;
|
|
4
|
+
name: string;
|
|
5
|
+
}>(providers: readonly T[]): T[];
|
|
6
|
+
export declare function separatesGroups(previous: AgentKind | undefined, kind: AgentKind): boolean;
|
|
2
7
|
export declare const COMPACT_MODEL_LIMIT = 8;
|
|
3
8
|
export type PickerEntry = {
|
|
4
9
|
kind: 'model';
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
import { pickerGroupsOf, providerGroupOf } from '@adecore/agent-contracts';
|
|
1
2
|
import { nameCollator } from '@adecore/ui/format';
|
|
3
|
+
/* The providers in the order a picker lists them: the frontier labs, the rest, then the API providers, each by name. */
|
|
4
|
+
export function inPickerOrder(providers) {
|
|
5
|
+
const groups = pickerGroupsOf(providers);
|
|
6
|
+
return [...groups.frontier, ...groups.others, ...groups.api];
|
|
7
|
+
}
|
|
8
|
+
/* Whether a separator goes between two providers next to each other in that order: where one group ends. */
|
|
9
|
+
export function separatesGroups(previous, kind) {
|
|
10
|
+
return previous !== undefined && providerGroupOf(previous) !== providerGroupOf(kind);
|
|
11
|
+
}
|
|
2
12
|
/*
|
|
3
13
|
* A provider with more live models than this keeps the list short: the model that is picked and the default,
|
|
4
14
|
* with the rest behind one row that opens all of them. A list of three hundred models is not one to scroll.
|
package/dist/chat/ui/Pickers.js
CHANGED
|
@@ -10,7 +10,7 @@ import { useChatHost } from '../../host.js';
|
|
|
10
10
|
import { ChatScopeContext } from '../../scope.js';
|
|
11
11
|
import { useReportedModels } from '../../state/chats.js';
|
|
12
12
|
import { ModelMarks } from './ModelMarks.js';
|
|
13
|
-
import { pickerEntriesOf } from '../logic/picker-entries.js';
|
|
13
|
+
import { inPickerOrder, pickerEntriesOf, separatesGroups } from '../logic/picker-entries.js';
|
|
14
14
|
import { favoriteModelsOf, toggleFavoriteModel, useChatPreferences } from '../preferences.js';
|
|
15
15
|
import { forgetStashed, STASH_SHORTCUT, useStash } from '../stash.js';
|
|
16
16
|
import { Button, Icon, IconButton, Menu, Popover, Tooltip } from '@adecore/ui';
|
|
@@ -23,7 +23,7 @@ const triggerClass = 'flex h-7 shrink-0 items-center gap-1 whitespace-nowrap rou
|
|
|
23
23
|
* provider's model is also how a chat picks its provider; with one CLI the group headers drop.
|
|
24
24
|
*/
|
|
25
25
|
export function ModelPicker(t0) {
|
|
26
|
-
const $ = _c(
|
|
26
|
+
const $ = _c(49);
|
|
27
27
|
const {
|
|
28
28
|
providers,
|
|
29
29
|
provider,
|
|
@@ -111,7 +111,7 @@ export function ModelPicker(t0) {
|
|
|
111
111
|
} else {
|
|
112
112
|
t8 = $[15];
|
|
113
113
|
}
|
|
114
|
-
const entries = pickerEntriesOf(providers, trimmed, legacyOpen, expanded, {
|
|
114
|
+
const entries = pickerEntriesOf(inPickerOrder(providers), trimmed, legacyOpen, expanded, {
|
|
115
115
|
provider,
|
|
116
116
|
model: selection.model
|
|
117
117
|
}, t8);
|
|
@@ -127,6 +127,10 @@ export function ModelPicker(t0) {
|
|
|
127
127
|
t9 = $[17];
|
|
128
128
|
}
|
|
129
129
|
const requirementOf = t9;
|
|
130
|
+
const kindBefore = i => {
|
|
131
|
+
const before = entries[i - 1];
|
|
132
|
+
return before === undefined || before.kind === "legacy" ? undefined : before.provider.kind;
|
|
133
|
+
};
|
|
130
134
|
let t10;
|
|
131
135
|
if ($[18] !== requirementOf) {
|
|
132
136
|
t10 = entry_1 => entry_1.kind === "model" && requirementOf(entry_1) !== null ? [entry_1.provider.kind] : [];
|
|
@@ -173,83 +177,63 @@ export function ModelPicker(t0) {
|
|
|
173
177
|
t13 = $[24];
|
|
174
178
|
}
|
|
175
179
|
useEffect(t12, t13);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
} else {
|
|
210
|
-
t14 = $[28];
|
|
211
|
-
}
|
|
212
|
-
const choose = t14;
|
|
213
|
-
let t15;
|
|
214
|
-
if ($[29] !== choose || $[30] !== entries || $[31] !== index) {
|
|
215
|
-
t15 = e => {
|
|
216
|
-
if (e.key === "ArrowDown") {
|
|
180
|
+
const choose = entry_2 => {
|
|
181
|
+
if (!entry_2) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (entry_2.kind === "legacy") {
|
|
185
|
+
setLegacyOpen(true);
|
|
186
|
+
inputRef.current?.focus();
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (entry_2.kind === "all") {
|
|
190
|
+
const kind_0 = entry_2.provider.kind;
|
|
191
|
+
setExpanded(now => {
|
|
192
|
+
const next_0 = new Set(now);
|
|
193
|
+
if (!next_0.delete(kind_0)) {
|
|
194
|
+
next_0.add(kind_0);
|
|
195
|
+
}
|
|
196
|
+
return next_0;
|
|
197
|
+
});
|
|
198
|
+
inputRef.current?.focus();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (requirementOf(entry_2) !== null) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
onChange(entry_2.provider.kind, entry_2.model.slug);
|
|
205
|
+
setOpen(false);
|
|
206
|
+
};
|
|
207
|
+
const onKeyDown = e => {
|
|
208
|
+
if (e.key === "ArrowDown") {
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
setIndex(i_0 => entries.length === 0 ? 0 : (i_0 + 1) % entries.length);
|
|
211
|
+
} else {
|
|
212
|
+
if (e.key === "ArrowUp") {
|
|
217
213
|
e.preventDefault();
|
|
218
|
-
setIndex(
|
|
214
|
+
setIndex(i_1 => entries.length === 0 ? 0 : (i_1 - 1 + entries.length) % entries.length);
|
|
219
215
|
} else {
|
|
220
|
-
if (e.key === "
|
|
216
|
+
if (e.key === "Enter") {
|
|
221
217
|
e.preventDefault();
|
|
222
|
-
|
|
223
|
-
} else {
|
|
224
|
-
if (e.key === "Enter") {
|
|
225
|
-
e.preventDefault();
|
|
226
|
-
choose(entries[index]);
|
|
227
|
-
}
|
|
218
|
+
choose(entries[index]);
|
|
228
219
|
}
|
|
229
220
|
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
let t14;
|
|
224
|
+
if ($[25] !== current || $[26] !== owner || $[27] !== t) {
|
|
225
|
+
t14 = owner ? `${owner.name} · ${current}` : t("pickers.model.choose");
|
|
226
|
+
$[25] = current;
|
|
227
|
+
$[26] = owner;
|
|
228
|
+
$[27] = t;
|
|
229
|
+
$[28] = t14;
|
|
235
230
|
} else {
|
|
236
|
-
|
|
231
|
+
t14 = $[28];
|
|
237
232
|
}
|
|
238
|
-
const
|
|
233
|
+
const t15 = kbd ?? undefined;
|
|
239
234
|
let t16;
|
|
240
|
-
if ($[
|
|
241
|
-
t16 =
|
|
242
|
-
$[33] = current;
|
|
243
|
-
$[34] = owner;
|
|
244
|
-
$[35] = t;
|
|
245
|
-
$[36] = t16;
|
|
246
|
-
} else {
|
|
247
|
-
t16 = $[36];
|
|
248
|
-
}
|
|
249
|
-
const t17 = kbd ?? undefined;
|
|
250
|
-
let t18;
|
|
251
|
-
if ($[37] !== chip || $[38] !== current || $[39] !== provider || $[40] !== trigger) {
|
|
252
|
-
t18 = trigger === "chip" ? /*#__PURE__*/_jsxs(Popover.Trigger, {
|
|
235
|
+
if ($[29] !== chip || $[30] !== current || $[31] !== provider || $[32] !== trigger) {
|
|
236
|
+
t16 = trigger === "chip" ? /*#__PURE__*/_jsxs(Popover.Trigger, {
|
|
253
237
|
render: /*#__PURE__*/_jsx(Button, {
|
|
254
238
|
variant: "secondary",
|
|
255
239
|
size: "sm",
|
|
@@ -286,117 +270,89 @@ export function ModelPicker(t0) {
|
|
|
286
270
|
className: "text-text-faint"
|
|
287
271
|
})]
|
|
288
272
|
});
|
|
289
|
-
$[
|
|
290
|
-
$[
|
|
291
|
-
$[
|
|
292
|
-
$[
|
|
293
|
-
$[
|
|
294
|
-
} else {
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
let
|
|
298
|
-
if ($[
|
|
299
|
-
|
|
300
|
-
label:
|
|
301
|
-
kbd:
|
|
302
|
-
children:
|
|
273
|
+
$[29] = chip;
|
|
274
|
+
$[30] = current;
|
|
275
|
+
$[31] = provider;
|
|
276
|
+
$[32] = trigger;
|
|
277
|
+
$[33] = t16;
|
|
278
|
+
} else {
|
|
279
|
+
t16 = $[33];
|
|
280
|
+
}
|
|
281
|
+
let t17;
|
|
282
|
+
if ($[34] !== t14 || $[35] !== t15 || $[36] !== t16) {
|
|
283
|
+
t17 = /*#__PURE__*/_jsx(Tooltip, {
|
|
284
|
+
label: t14,
|
|
285
|
+
kbd: t15,
|
|
286
|
+
children: t16
|
|
303
287
|
});
|
|
304
|
-
$[
|
|
305
|
-
$[
|
|
306
|
-
$[
|
|
307
|
-
$[
|
|
288
|
+
$[34] = t14;
|
|
289
|
+
$[35] = t15;
|
|
290
|
+
$[36] = t16;
|
|
291
|
+
$[37] = t17;
|
|
308
292
|
} else {
|
|
309
|
-
|
|
293
|
+
t17 = $[37];
|
|
310
294
|
}
|
|
311
|
-
let
|
|
312
|
-
if ($[
|
|
313
|
-
|
|
295
|
+
let t18;
|
|
296
|
+
if ($[38] !== finalFocus) {
|
|
297
|
+
t18 = finalFocus === undefined ? {} : {
|
|
314
298
|
finalFocus
|
|
315
299
|
};
|
|
316
|
-
$[
|
|
317
|
-
$[
|
|
300
|
+
$[38] = finalFocus;
|
|
301
|
+
$[39] = t18;
|
|
318
302
|
} else {
|
|
319
|
-
|
|
303
|
+
t18 = $[39];
|
|
320
304
|
}
|
|
321
|
-
let
|
|
322
|
-
if ($[
|
|
323
|
-
|
|
305
|
+
let t19;
|
|
306
|
+
if ($[40] === Symbol.for("react.memo_cache_sentinel")) {
|
|
307
|
+
t19 = /*#__PURE__*/_jsx(Icon, {
|
|
324
308
|
icon: Search,
|
|
325
309
|
size: 14,
|
|
326
310
|
className: "shrink-0 text-text-faint"
|
|
327
311
|
});
|
|
328
|
-
$[
|
|
312
|
+
$[40] = t19;
|
|
329
313
|
} else {
|
|
330
|
-
|
|
314
|
+
t19 = $[40];
|
|
331
315
|
}
|
|
332
|
-
let
|
|
333
|
-
if ($[
|
|
334
|
-
|
|
335
|
-
$[
|
|
336
|
-
$[
|
|
316
|
+
let t20;
|
|
317
|
+
if ($[41] !== t) {
|
|
318
|
+
t20 = t("pickers.model.search");
|
|
319
|
+
$[41] = t;
|
|
320
|
+
$[42] = t20;
|
|
337
321
|
} else {
|
|
338
|
-
|
|
322
|
+
t20 = $[42];
|
|
339
323
|
}
|
|
340
|
-
let
|
|
341
|
-
if ($[
|
|
342
|
-
|
|
324
|
+
let t21;
|
|
325
|
+
if ($[43] === Symbol.for("react.memo_cache_sentinel")) {
|
|
326
|
+
t21 = e_0 => {
|
|
343
327
|
setQuery(e_0.target.value);
|
|
344
328
|
setIndex(0);
|
|
345
329
|
};
|
|
346
|
-
$[
|
|
330
|
+
$[43] = t21;
|
|
347
331
|
} else {
|
|
348
|
-
|
|
332
|
+
t21 = $[43];
|
|
349
333
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
placeholder: t22,
|
|
358
|
-
spellCheck: false,
|
|
359
|
-
value: query,
|
|
360
|
-
onChange: t23,
|
|
361
|
-
onKeyDown: onKeyDown
|
|
362
|
-
})]
|
|
363
|
-
});
|
|
364
|
-
$[52] = onKeyDown;
|
|
365
|
-
$[53] = query;
|
|
366
|
-
$[54] = t22;
|
|
367
|
-
$[55] = t24;
|
|
368
|
-
} else {
|
|
369
|
-
t24 = $[55];
|
|
370
|
-
}
|
|
371
|
-
let t25;
|
|
372
|
-
if ($[56] !== entries.length || $[57] !== providers.length || $[58] !== t) {
|
|
373
|
-
t25 = entries.length === 0 && /*#__PURE__*/_jsx("div", {
|
|
374
|
-
className: "px-3 py-6 text-center text-xs text-text-faint",
|
|
375
|
-
children: providers.length === 0 ? t("pickers.model.noProvider") : t("pickers.model.noMatch")
|
|
376
|
-
});
|
|
377
|
-
$[56] = entries.length;
|
|
378
|
-
$[57] = providers.length;
|
|
379
|
-
$[58] = t;
|
|
380
|
-
$[59] = t25;
|
|
381
|
-
} else {
|
|
382
|
-
t25 = $[59];
|
|
383
|
-
}
|
|
384
|
-
const t26 = entries.map((entry_3, i_1) => {
|
|
334
|
+
const t22 = "max-h-72 overflow-auto p-1";
|
|
335
|
+
const t23 = "listbox";
|
|
336
|
+
const t24 = entries.length === 0 && /*#__PURE__*/_jsx("div", {
|
|
337
|
+
className: "px-3 py-6 text-center text-xs text-text-faint",
|
|
338
|
+
children: providers.length === 0 ? t("pickers.model.noProvider") : t("pickers.model.noMatch")
|
|
339
|
+
});
|
|
340
|
+
const t25 = entries.map((entry_3, i_2) => {
|
|
385
341
|
if (entry_3.kind === "all") {
|
|
386
|
-
const
|
|
387
|
-
const header = grouped && (
|
|
342
|
+
const before_0 = entries[i_2 - 1];
|
|
343
|
+
const header = grouped && (before_0 === undefined || before_0.kind === "legacy" || before_0.provider.kind !== entry_3.provider.kind);
|
|
388
344
|
return /*#__PURE__*/_jsxs("div", {
|
|
389
|
-
children: [header && /*#__PURE__*/_jsxs(Menu.Label, {
|
|
345
|
+
children: [separatesGroups(kindBefore(i_2), entry_3.provider.kind) && /*#__PURE__*/_jsx(Menu.Separator, {}), header && /*#__PURE__*/_jsxs(Menu.Label, {
|
|
390
346
|
className: "flex items-center gap-1.5",
|
|
391
347
|
children: [/*#__PURE__*/_jsx(AgentIcon, {
|
|
392
348
|
kind: entry_3.provider.kind,
|
|
393
349
|
size: 12
|
|
394
350
|
}), entry_3.provider.name]
|
|
395
351
|
}), /*#__PURE__*/_jsxs("button", {
|
|
396
|
-
"data-active":
|
|
352
|
+
"data-active": i_2 === index,
|
|
397
353
|
"aria-expanded": entry_3.open,
|
|
398
354
|
className: "cursor-row flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-xs text-text-muted",
|
|
399
|
-
onMouseEnter: () => setIndex(
|
|
355
|
+
onMouseEnter: () => setIndex(i_2),
|
|
400
356
|
onClick: () => choose(entry_3),
|
|
401
357
|
children: [/*#__PURE__*/_jsx(Icon, {
|
|
402
358
|
icon: entry_3.open ? ChevronDown : ChevronRight,
|
|
@@ -409,9 +365,9 @@ export function ModelPicker(t0) {
|
|
|
409
365
|
}
|
|
410
366
|
if (entry_3.kind === "legacy") {
|
|
411
367
|
return /*#__PURE__*/_jsxs("button", {
|
|
412
|
-
"data-active":
|
|
368
|
+
"data-active": i_2 === index,
|
|
413
369
|
className: "cursor-row flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-xs text-text-faint",
|
|
414
|
-
onMouseEnter: () => setIndex(
|
|
370
|
+
onMouseEnter: () => setIndex(i_2),
|
|
415
371
|
onClick: () => choose(entry_3),
|
|
416
372
|
children: [/*#__PURE__*/_jsx(Icon, {
|
|
417
373
|
icon: legacyOpen ? ChevronDown : ChevronRight,
|
|
@@ -421,17 +377,17 @@ export function ModelPicker(t0) {
|
|
|
421
377
|
})]
|
|
422
378
|
}, "legacy");
|
|
423
379
|
}
|
|
424
|
-
const previous = entries[
|
|
380
|
+
const previous = entries[i_2 - 1];
|
|
425
381
|
const first = grouped && (previous === undefined || previous.kind === "legacy" || previous.provider.kind !== entry_3.provider.kind);
|
|
426
382
|
const vendorOpen = trimmed !== "" || expanded.has(entry_3.provider.kind);
|
|
427
383
|
const vendorFirst = vendorOpen && entry_3.model.vendor !== undefined && !starredHere(entry_3) && (previous === undefined || previous.kind !== "model" || previous.provider.kind !== entry_3.provider.kind || starredHere(previous) || previous.model.vendor !== entry_3.model.vendor);
|
|
428
384
|
const requirement = requirementOf(entry_3);
|
|
429
|
-
const next_1 = entries[
|
|
385
|
+
const next_1 = entries[i_2 + 1];
|
|
430
386
|
const lastOfGroup = next_1 === undefined || next_1.kind !== "model" || next_1.provider.kind !== entry_3.provider.kind;
|
|
431
387
|
const chosen = entry_3.provider.kind === provider && entry_3.model.slug === selection.model;
|
|
432
388
|
const starred = starredHere(entry_3);
|
|
433
389
|
return /*#__PURE__*/_jsxs("div", {
|
|
434
|
-
children: [first && /*#__PURE__*/_jsxs(Menu.Label, {
|
|
390
|
+
children: [separatesGroups(kindBefore(i_2), entry_3.provider.kind) && /*#__PURE__*/_jsx(Menu.Separator, {}), first && /*#__PURE__*/_jsxs(Menu.Label, {
|
|
435
391
|
className: "flex items-center gap-1.5",
|
|
436
392
|
children: [/*#__PURE__*/_jsx(AgentIcon, {
|
|
437
393
|
kind: entry_3.provider.kind,
|
|
@@ -445,9 +401,9 @@ export function ModelPicker(t0) {
|
|
|
445
401
|
role: "option",
|
|
446
402
|
"aria-selected": chosen,
|
|
447
403
|
"aria-disabled": requirement !== null || undefined,
|
|
448
|
-
"data-active":
|
|
404
|
+
"data-active": i_2 === index,
|
|
449
405
|
className: `cursor-row flex min-w-0 grow flex-col items-stretch gap-0.5 rounded-md px-2.5 py-1.5 text-left text-sm ${requirement === null ? "text-text-muted" : "text-text-faint"}`,
|
|
450
|
-
onMouseEnter: () => setIndex(
|
|
406
|
+
onMouseEnter: () => setIndex(i_2),
|
|
451
407
|
onClick: () => choose(entry_3),
|
|
452
408
|
children: [/*#__PURE__*/_jsxs("span", {
|
|
453
409
|
className: "flex w-full items-center gap-2",
|
|
@@ -496,65 +452,53 @@ export function ModelPicker(t0) {
|
|
|
496
452
|
})]
|
|
497
453
|
}, `${entry_3.provider.kind}/${entry_3.model.slug}`);
|
|
498
454
|
});
|
|
499
|
-
let
|
|
500
|
-
if ($[
|
|
501
|
-
|
|
455
|
+
let t26;
|
|
456
|
+
if ($[44] !== t24 || $[45] !== t25) {
|
|
457
|
+
t26 = /*#__PURE__*/_jsxs("div", {
|
|
502
458
|
ref: listRef,
|
|
503
|
-
className:
|
|
504
|
-
role:
|
|
505
|
-
children: [
|
|
459
|
+
className: t22,
|
|
460
|
+
role: t23,
|
|
461
|
+
children: [t24, t25]
|
|
506
462
|
});
|
|
507
|
-
$[
|
|
508
|
-
$[
|
|
509
|
-
$[
|
|
463
|
+
$[44] = t24;
|
|
464
|
+
$[45] = t25;
|
|
465
|
+
$[46] = t26;
|
|
510
466
|
} else {
|
|
511
|
-
|
|
467
|
+
t26 = $[46];
|
|
512
468
|
}
|
|
513
|
-
let
|
|
514
|
-
if ($[
|
|
515
|
-
|
|
469
|
+
let t27;
|
|
470
|
+
if ($[47] !== footer) {
|
|
471
|
+
t27 = footer !== undefined && /*#__PURE__*/_jsx("div", {
|
|
516
472
|
className: "border-t border-border-soft px-3 py-2 text-xs text-text-faint",
|
|
517
473
|
children: footer
|
|
518
474
|
});
|
|
519
|
-
$[
|
|
520
|
-
$[
|
|
475
|
+
$[47] = footer;
|
|
476
|
+
$[48] = t27;
|
|
521
477
|
} else {
|
|
522
|
-
|
|
478
|
+
t27 = $[48];
|
|
523
479
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
480
|
+
return /*#__PURE__*/_jsxs(Popover.Root, {
|
|
481
|
+
open: open,
|
|
482
|
+
onOpenChange: setOpen,
|
|
483
|
+
children: [t17, /*#__PURE__*/_jsxs(Popover.Popup, {
|
|
527
484
|
variant: "picker",
|
|
528
485
|
side: side,
|
|
529
486
|
initialFocus: inputRef,
|
|
530
|
-
...
|
|
531
|
-
children: [
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
open: open,
|
|
546
|
-
onOpenChange: setOpen,
|
|
547
|
-
children: [t19, t29]
|
|
548
|
-
});
|
|
549
|
-
$[71] = open;
|
|
550
|
-
$[72] = setOpen;
|
|
551
|
-
$[73] = t19;
|
|
552
|
-
$[74] = t29;
|
|
553
|
-
$[75] = t30;
|
|
554
|
-
} else {
|
|
555
|
-
t30 = $[75];
|
|
556
|
-
}
|
|
557
|
-
return t30;
|
|
487
|
+
...t18,
|
|
488
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
489
|
+
className: "flex items-center gap-2 border-b border-border px-2.5",
|
|
490
|
+
children: [t19, /*#__PURE__*/_jsx("input", {
|
|
491
|
+
ref: inputRef,
|
|
492
|
+
className: "h-8 w-full bg-transparent text-sm text-text outline-none placeholder:text-text-faint",
|
|
493
|
+
placeholder: t20,
|
|
494
|
+
spellCheck: false,
|
|
495
|
+
value: query,
|
|
496
|
+
onChange: t21,
|
|
497
|
+
onKeyDown: onKeyDown
|
|
498
|
+
})]
|
|
499
|
+
}), t26, t27]
|
|
500
|
+
})]
|
|
501
|
+
});
|
|
558
502
|
}
|
|
559
503
|
/*
|
|
560
504
|
* Prompts put aside with Cmd+S, on a shelf the whole app shares, since a stashed prompt usually moves
|
|
@@ -10,7 +10,7 @@ import { AgentIcon } from '../../agents/AgentIcon.js';
|
|
|
10
10
|
import { modelName, shortModelName } from '../../agents/model-name.js';
|
|
11
11
|
import { ModelMarks } from './ModelMarks.js';
|
|
12
12
|
import { SessionLine } from './SessionLine.js';
|
|
13
|
-
import { favoritesFirst, searchModels, shortlistOf, wantsModelSearch } from '../logic/picker-entries.js';
|
|
13
|
+
import { favoritesFirst, inPickerOrder, searchModels, separatesGroups, shortlistOf, wantsModelSearch } from '../logic/picker-entries.js';
|
|
14
14
|
import { favoriteModelsOf, toggleFavoriteModel, useChatPreferences } from '../preferences.js';
|
|
15
15
|
import { CONTEXT_OPTION, contextFraction, contextSegments, orderOptions } from '../logic/context-usage.js';
|
|
16
16
|
import { RUNTIME_MODES } from '../runtime-modes.js';
|
|
@@ -56,7 +56,7 @@ function modelValue(provider, slug) {
|
|
|
56
56
|
}
|
|
57
57
|
/* Each provider's current or legacy models; a provider with none of them is left out. */
|
|
58
58
|
function modelGroupsOf(providers, legacy) {
|
|
59
|
-
return providers.map(entry => ({
|
|
59
|
+
return inPickerOrder(providers).map(entry => ({
|
|
60
60
|
entry,
|
|
61
61
|
models: entry.models.filter(row => row.legacy === true === legacy)
|
|
62
62
|
})).filter(group => group.models.length > 0);
|
|
@@ -196,7 +196,7 @@ export function RunSettings(t0) {
|
|
|
196
196
|
const favoritesOf = t8;
|
|
197
197
|
let t9;
|
|
198
198
|
if ($[19] !== favoritesOf || $[20] !== providers || $[21] !== query) {
|
|
199
|
-
t9 = query.trim() === "" ? null : searchModels(providers, query, favoritesOf);
|
|
199
|
+
t9 = query.trim() === "" ? null : searchModels(inPickerOrder(providers), query, favoritesOf);
|
|
200
200
|
$[19] = favoritesOf;
|
|
201
201
|
$[20] = providers;
|
|
202
202
|
$[21] = query;
|
|
@@ -391,19 +391,21 @@ export function RunSettings(t0) {
|
|
|
391
391
|
const providerModels = t17;
|
|
392
392
|
let t18;
|
|
393
393
|
if ($[51] !== grouped || $[52] !== providerModels) {
|
|
394
|
-
t18 = groups => groups.map(t19 => {
|
|
394
|
+
t18 = groups => groups.map((t19, i_0) => {
|
|
395
395
|
const {
|
|
396
396
|
entry: entry_3,
|
|
397
397
|
models: models_1
|
|
398
398
|
} = t19;
|
|
399
|
-
return /*#__PURE__*/_jsxs(
|
|
400
|
-
children: [
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
399
|
+
return /*#__PURE__*/_jsxs(Fragment, {
|
|
400
|
+
children: [separatesGroups(groups[i_0 - 1]?.entry.kind, entry_3.kind) && /*#__PURE__*/_jsx(Menu.Separator, {}), /*#__PURE__*/_jsxs(Menu.Group, {
|
|
401
|
+
children: [grouped && /*#__PURE__*/_jsxs(Menu.GroupLabel, {
|
|
402
|
+
className: "flex items-center gap-1.5",
|
|
403
|
+
children: [/*#__PURE__*/_jsx(AgentIcon, {
|
|
404
|
+
kind: entry_3.kind,
|
|
405
|
+
size: 12
|
|
406
|
+
}), entry_3.name]
|
|
407
|
+
}), providerModels(entry_3, models_1)]
|
|
408
|
+
})]
|
|
407
409
|
}, entry_3.kind);
|
|
408
410
|
});
|
|
409
411
|
$[51] = grouped;
|
|
@@ -657,19 +659,21 @@ export function RunSettings(t0) {
|
|
|
657
659
|
t47 = found !== null && found.length > 0 && /*#__PURE__*/_jsx(Menu.RadioGroup, {
|
|
658
660
|
value: chosenModel,
|
|
659
661
|
onValueChange: chooseModel,
|
|
660
|
-
children: found.map(t48 => {
|
|
662
|
+
children: found.map((t48, i_1) => {
|
|
661
663
|
const {
|
|
662
664
|
entry: entry_5,
|
|
663
665
|
models: models_2
|
|
664
666
|
} = t48;
|
|
665
|
-
return /*#__PURE__*/_jsxs(
|
|
666
|
-
children: [
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
667
|
+
return /*#__PURE__*/_jsxs(Fragment, {
|
|
668
|
+
children: [separatesGroups(found[i_1 - 1]?.entry.kind, entry_5.kind) && /*#__PURE__*/_jsx(Menu.Separator, {}), /*#__PURE__*/_jsxs(Menu.Group, {
|
|
669
|
+
children: [grouped && /*#__PURE__*/_jsxs(Menu.GroupLabel, {
|
|
670
|
+
className: "flex items-center gap-1.5",
|
|
671
|
+
children: [/*#__PURE__*/_jsx(AgentIcon, {
|
|
672
|
+
kind: entry_5.kind,
|
|
673
|
+
size: 12
|
|
674
|
+
}), entry_5.name]
|
|
675
|
+
}), byMaker(entry_5, models_2)]
|
|
676
|
+
})]
|
|
673
677
|
}, entry_5.kind);
|
|
674
678
|
})
|
|
675
679
|
});
|
package/dist/providers/parts.js
CHANGED
|
@@ -10,7 +10,8 @@ const CLI_COLORS = {
|
|
|
10
10
|
gemini: 'text-chart-gemini',
|
|
11
11
|
copilot: 'text-chart-copilot',
|
|
12
12
|
nanogpt: 'text-chart-nanogpt',
|
|
13
|
-
grok: 'text-chart-grok'
|
|
13
|
+
grok: 'text-chart-grok',
|
|
14
|
+
'anthropic-claude-api': 'text-chart-claude-api'
|
|
14
15
|
};
|
|
15
16
|
export function CliMark(t0) {
|
|
16
17
|
const $ = _c(7);
|
package/dist/theme.css
CHANGED
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
--skill: #9333ea;
|
|
9
9
|
--skill-soft: #f7eeff;
|
|
10
10
|
/* One color per agent CLI, so a bar, a dot and a legend row all name the same provider. Apple's
|
|
11
|
-
system orange and teal
|
|
11
|
+
system orange and teal, and purple for Claude through an API key so it reads apart from Claude Code;
|
|
12
|
+
Gemini and Copilot are reserved for the day their transcripts are read. */
|
|
12
13
|
--chart-claude: #ff9500;
|
|
14
|
+
--chart-claude-api: #af52de;
|
|
13
15
|
--chart-codex: #30b0c7;
|
|
14
16
|
--chart-gemini: #3b82f6;
|
|
15
17
|
--chart-copilot: #64748b;
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
--skill: #c084fc;
|
|
38
40
|
--skill-soft: #2f2350;
|
|
39
41
|
--chart-claude: #ff9f0a;
|
|
42
|
+
--chart-claude-api: #bf5af2;
|
|
40
43
|
--chart-codex: #40c8e0;
|
|
41
44
|
--chart-gemini: #60a5fa;
|
|
42
45
|
--chart-copilot: #94a3b8;
|
|
@@ -70,6 +73,7 @@
|
|
|
70
73
|
--color-skill: var(--skill);
|
|
71
74
|
--color-skill-soft: var(--skill-soft);
|
|
72
75
|
--color-chart-claude: var(--chart-claude);
|
|
76
|
+
--color-chart-claude-api: var(--chart-claude-api);
|
|
73
77
|
--color-chart-codex: var(--chart-codex);
|
|
74
78
|
--color-chart-gemini: var(--chart-gemini);
|
|
75
79
|
--color-chart-copilot: var(--chart-copilot);
|
package/dist/usage/format.js
CHANGED
|
@@ -25,14 +25,16 @@ export const PROVIDER_LABELS = {
|
|
|
25
25
|
codex: 'Codex',
|
|
26
26
|
nanogpt: 'NanoGPT',
|
|
27
27
|
grok: 'Grok',
|
|
28
|
-
copilot: 'GitHub Copilot'
|
|
28
|
+
copilot: 'GitHub Copilot',
|
|
29
|
+
'anthropic-claude-api': 'Claude API'
|
|
29
30
|
};
|
|
30
31
|
export const PROVIDER_COLORS = {
|
|
31
32
|
claude: 'var(--chart-claude)',
|
|
32
33
|
codex: 'var(--chart-codex)',
|
|
33
34
|
nanogpt: 'var(--chart-nanogpt)',
|
|
34
35
|
grok: 'var(--chart-grok)',
|
|
35
|
-
copilot: 'var(--chart-copilot)'
|
|
36
|
+
copilot: 'var(--chart-copilot)',
|
|
37
|
+
'anthropic-claude-api': 'var(--chart-claude-api)'
|
|
36
38
|
};
|
|
37
39
|
/*
|
|
38
40
|
* A slot is `2026-09-10` or `2026-09-10T14`, already in the viewer's own zone, so it is read as plain
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents-react",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.2",
|
|
4
4
|
"description": "React agent chat threads, composers, approvals, provider accounts and usage views.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"test:visuals": "bun --config=integration.bunfig.toml --conditions=source test ./src/chat/visual-viewport.integration.test.ts"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@adecore/agent-contracts": "0.37.
|
|
71
|
-
"@adecore/editor": "0.37.
|
|
72
|
-
"@adecore/editor-react": "0.37.
|
|
73
|
-
"@adecore/intelligent-ui": "0.37.
|
|
74
|
-
"@adecore/merge": "0.37.
|
|
70
|
+
"@adecore/agent-contracts": "0.37.2",
|
|
71
|
+
"@adecore/editor": "0.37.2",
|
|
72
|
+
"@adecore/editor-react": "0.37.2",
|
|
73
|
+
"@adecore/intelligent-ui": "0.37.2",
|
|
74
|
+
"@adecore/merge": "0.37.2",
|
|
75
75
|
"@codemirror/commands": "^6.11.1",
|
|
76
76
|
"@codemirror/language": "^6.12.4",
|
|
77
77
|
"@codemirror/state": "^6.7.6",
|
|
@@ -94,14 +94,14 @@
|
|
|
94
94
|
"zustand": "^5.0.15"
|
|
95
95
|
},
|
|
96
96
|
"peerDependencies": {
|
|
97
|
-
"@adecore/ui": "^0.37.
|
|
97
|
+
"@adecore/ui": "^0.37.2",
|
|
98
98
|
"i18next": "^26.4.2",
|
|
99
99
|
"react": "^19.3.0",
|
|
100
100
|
"react-dom": "^19.3.0",
|
|
101
101
|
"react-i18next": "^17.0.15"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@adecore/ui": "0.37.
|
|
104
|
+
"@adecore/ui": "0.37.2",
|
|
105
105
|
"@types/bun": "^1.4.2",
|
|
106
106
|
"@types/react": "^19.3.0",
|
|
107
107
|
"@types/react-dom": "^19.3.0",
|
|
@@ -5,8 +5,12 @@ import { siGithubcopilot } from 'simple-icons';
|
|
|
5
5
|
* The marks of Anthropic, OpenAI, xAI and GitHub Copilot, and a monogram for a provider with no mark of its own. Lucide has no brand marks, so these are the icon rule's
|
|
6
6
|
* exception for provider marks. One path each, in `currentColor`, so a row decides how loud the logo is.
|
|
7
7
|
*/
|
|
8
|
+
const CLAUDE_PATH =
|
|
9
|
+
'M4.709 15.955l4.72-2.647.079-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.377-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.048.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.607.212-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.914-1.316-.012.01z';
|
|
10
|
+
|
|
8
11
|
export const PROVIDER_PATHS: Record<UsageProvider, string> = {
|
|
9
|
-
claude:
|
|
12
|
+
claude: CLAUDE_PATH,
|
|
13
|
+
'anthropic-claude-api': CLAUDE_PATH,
|
|
10
14
|
codex: 'M21.55 10.004a5.416 5.416 0 00-.478-4.501c-1.217-2.09-3.662-3.166-6.05-2.66A5.59 5.59 0 0010.831 1C8.39.995 6.224 2.546 5.473 4.838A5.553 5.553 0 001.76 7.496a5.487 5.487 0 00.691 6.5 5.416 5.416 0 00.477 4.502c1.217 2.09 3.662 3.165 6.05 2.66A5.586 5.586 0 0013.168 23c2.443.006 4.61-1.546 5.361-3.84a5.554 5.554 0 003.715-2.66 5.488 5.488 0 00-.693-6.497v.001zm-8.381 11.558a4.199 4.199 0 01-2.675-.954c.034-.018.093-.05.132-.074l4.44-2.53a.71.71 0 00.364-.623v-6.176l1.877 1.069c.02.01.033.029.036.05v5.115c-.003 2.274-1.87 4.118-4.174 4.123zM4.192 17.78a4.059 4.059 0 01-.498-2.763c.032.019.09.055.131.078l4.44 2.53c.225.13.504.13.73 0l5.42-3.088v2.138a.068.068 0 01-.027.057L9.9 19.288c-1.999 1.136-4.552.46-5.707-1.51h-.001zM3.023 8.216A4.15 4.15 0 015.198 6.41l-.002.151v5.06a.711.711 0 00.364.624l5.42 3.087-1.876 1.07a.067.067 0 01-.063.005l-4.489-2.559c-1.995-1.14-2.679-3.658-1.53-5.63h.001zm15.417 3.54l-5.42-3.088L14.896 7.6a.067.067 0 01.063-.006l4.489 2.557c1.998 1.14 2.683 3.662 1.529 5.633a4.163 4.163 0 01-2.174 1.807V12.38a.71.71 0 00-.363-.623zm1.867-2.773a6.04 6.04 0 00-.132-.078l-4.44-2.53a.731.731 0 00-.729 0l-5.42 3.088V7.325a.068.068 0 01.027-.057L14.1 4.713c2-1.137 4.555-.46 5.707 1.513.487.833.664 1.809.499 2.757h.001zm-11.741 3.81l-1.877-1.068a.065.065 0 01-.036-.051V6.559c.001-2.277 1.873-4.122 4.181-4.12.976 0 1.92.338 2.671.954-.034.018-.092.05-.131.073l-4.44 2.53a.71.71 0 00-.365.623l-.003 6.173v.001zm1.02-2.168L12 9.25l2.414 1.375v2.75L12 14.75l-2.415-1.375v-2.75z',
|
|
11
15
|
nanogpt: 'M5 20V4h2.6l8.8 11.2V4H19v16h-2.6L7.6 8.8V20z',
|
|
12
16
|
grok: 'M6.469 8.776 16.512 23h-4.464L2.005 8.776H6.47Zm-.004 7.9 2.233 3.164L6.467 23H2l4.465-6.324ZM22 2.582V23h-3.659V7.764L22 2.582ZM22 1l-9.952 14.095-2.233-3.163L17.533 1H22Z',
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { pickerGroupsOf, providerGroupOf, type AgentKind, type ModelInfo, type ProviderInfo } from '@adecore/agent-contracts';
|
|
2
2
|
import { nameCollator } from '@adecore/ui/format';
|
|
3
3
|
|
|
4
|
+
/* The providers in the order a picker lists them: the frontier labs, the rest, then the API providers, each by name. */
|
|
5
|
+
export function inPickerOrder<T extends { kind: AgentKind; name: string }>(providers: readonly T[]): T[] {
|
|
6
|
+
const groups = pickerGroupsOf(providers);
|
|
7
|
+
return [...groups.frontier, ...groups.others, ...groups.api];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* Whether a separator goes between two providers next to each other in that order: where one group ends. */
|
|
11
|
+
export function separatesGroups(previous: AgentKind | undefined, kind: AgentKind): boolean {
|
|
12
|
+
return previous !== undefined && providerGroupOf(previous) !== providerGroupOf(kind);
|
|
13
|
+
}
|
|
14
|
+
|
|
4
15
|
/*
|
|
5
16
|
* A provider with more live models than this keeps the list short: the model that is picked and the default,
|
|
6
17
|
* with the rest behind one row that opens all of them. A list of three hundred models is not one to scroll.
|
package/src/chat/ui/Pickers.tsx
CHANGED
|
@@ -10,7 +10,7 @@ import { useChatHost } from '../../host';
|
|
|
10
10
|
import { ChatScopeContext } from '../../scope';
|
|
11
11
|
import { useReportedModels } from '../../state/chats';
|
|
12
12
|
import { ModelMarks } from './ModelMarks';
|
|
13
|
-
import { pickerEntriesOf, type PickerEntry } from '../logic/picker-entries';
|
|
13
|
+
import { inPickerOrder, pickerEntriesOf, separatesGroups, type PickerEntry } from '../logic/picker-entries';
|
|
14
14
|
import { favoriteModelsOf, toggleFavoriteModel, useChatPreferences } from '../preferences';
|
|
15
15
|
import { forgetStashed, STASH_SHORTCUT, useStash, type StashedPrompt } from '../stash';
|
|
16
16
|
import { Button, Icon, IconButton, Menu, Popover, Tooltip } from '@adecore/ui';
|
|
@@ -75,7 +75,7 @@ export function ModelPicker({
|
|
|
75
75
|
|
|
76
76
|
const favorites = useChatPreferences((preferences) => preferences.favoriteModels);
|
|
77
77
|
const starredHere = (row: PickerEntry | undefined): boolean => row?.kind === 'model' && favorites[row.provider.kind]?.includes(row.model.slug) === true;
|
|
78
|
-
const entries = pickerEntriesOf(providers, trimmed, legacyOpen, expanded, { provider, model: selection.model }, (kind) =>
|
|
78
|
+
const entries = pickerEntriesOf(inPickerOrder(providers), trimmed, legacyOpen, expanded, { provider, model: selection.model }, (kind) =>
|
|
79
79
|
favoriteModelsOf(favorites, kind)
|
|
80
80
|
);
|
|
81
81
|
const scope = useContext(ChatScopeContext);
|
|
@@ -83,6 +83,10 @@ export function ModelPicker({
|
|
|
83
83
|
const reported = useReportedModels(provider);
|
|
84
84
|
const requirementOf = (entry: PickerEntry & { kind: 'model' }) => modelRequirementOf(entry.model, entry.provider, reported);
|
|
85
85
|
// A CLI that is too old blocks all its models; one way to its settings under the group says it once.
|
|
86
|
+
const kindBefore = (i: number): AgentKind | undefined => {
|
|
87
|
+
const before = entries[i - 1];
|
|
88
|
+
return before === undefined || before.kind === 'legacy' ? undefined : before.provider.kind;
|
|
89
|
+
};
|
|
86
90
|
const blockedKinds = new Set(entries.flatMap((entry) => (entry.kind === 'model' && requirementOf(entry) !== null ? [entry.provider.kind] : [])));
|
|
87
91
|
|
|
88
92
|
/* Closing forgets the search, so the next open (a click or `/model`) starts on the whole list. */
|
|
@@ -188,6 +192,7 @@ export function ModelPicker({
|
|
|
188
192
|
const header = grouped && (before === undefined || before.kind === 'legacy' || before.provider.kind !== entry.provider.kind);
|
|
189
193
|
return (
|
|
190
194
|
<div key={`all-${entry.provider.kind}`}>
|
|
195
|
+
{separatesGroups(kindBefore(i), entry.provider.kind) && <Menu.Separator />}
|
|
191
196
|
{header && (
|
|
192
197
|
<Menu.Label className="flex items-center gap-1.5">
|
|
193
198
|
<AgentIcon kind={entry.provider.kind} size={12} />
|
|
@@ -243,6 +248,7 @@ export function ModelPicker({
|
|
|
243
248
|
const starred = starredHere(entry);
|
|
244
249
|
return (
|
|
245
250
|
<div key={`${entry.provider.kind}/${entry.model.slug}`}>
|
|
251
|
+
{separatesGroups(kindBefore(i), entry.provider.kind) && <Menu.Separator />}
|
|
246
252
|
{first && (
|
|
247
253
|
<Menu.Label className="flex items-center gap-1.5">
|
|
248
254
|
<AgentIcon kind={entry.provider.kind} size={12} />
|
|
@@ -27,7 +27,7 @@ import type { AccountChoice } from '../account-choice';
|
|
|
27
27
|
import { modelName, shortModelName } from '../../agents/model-name';
|
|
28
28
|
import { ModelMarks } from './ModelMarks';
|
|
29
29
|
import { SessionLine } from './SessionLine';
|
|
30
|
-
import { favoritesFirst, searchModels, shortlistOf, wantsModelSearch } from '../logic/picker-entries';
|
|
30
|
+
import { favoritesFirst, inPickerOrder, searchModels, separatesGroups, shortlistOf, wantsModelSearch } from '../logic/picker-entries';
|
|
31
31
|
import { favoriteModelsOf, toggleFavoriteModel, useChatPreferences } from '../preferences';
|
|
32
32
|
import { CONTEXT_OPTION, contextFraction, contextSegments, orderOptions, type ContextPart } from '../logic/context-usage';
|
|
33
33
|
import { RUNTIME_MODES } from '../runtime-modes';
|
|
@@ -113,7 +113,7 @@ function modelValue(provider: AgentKind, slug: string): string {
|
|
|
113
113
|
|
|
114
114
|
/* Each provider's current or legacy models; a provider with none of them is left out. */
|
|
115
115
|
function modelGroupsOf(providers: ProviderInfo[], legacy: boolean): Array<{ entry: ProviderInfo; models: ModelInfo[] }> {
|
|
116
|
-
return providers
|
|
116
|
+
return inPickerOrder(providers)
|
|
117
117
|
.map((entry) => ({ entry, models: entry.models.filter((row) => (row.legacy === true) === legacy) }))
|
|
118
118
|
.filter((group) => group.models.length > 0);
|
|
119
119
|
}
|
|
@@ -177,7 +177,7 @@ export function RunSettings({
|
|
|
177
177
|
const searchable = wantsModelSearch(providers);
|
|
178
178
|
const favorites = useChatPreferences((preferences) => preferences.favoriteModels);
|
|
179
179
|
const favoritesOf = (kind: AgentKind): ReadonlySet<string> => favoriteModelsOf(favorites, kind);
|
|
180
|
-
const found = query.trim() === '' ? null : searchModels(providers, query, favoritesOf);
|
|
180
|
+
const found = query.trim() === '' ? null : searchModels(inPickerOrder(providers), query, favoritesOf);
|
|
181
181
|
|
|
182
182
|
// The menu moves the focus to its popup as it opens, so the search field takes it a frame later.
|
|
183
183
|
useEffect(() => {
|
|
@@ -292,16 +292,19 @@ export function RunSettings({
|
|
|
292
292
|
};
|
|
293
293
|
|
|
294
294
|
const modelGroups = (groups: typeof live) =>
|
|
295
|
-
groups.map(({ entry, models }) => (
|
|
296
|
-
<
|
|
297
|
-
{
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
295
|
+
groups.map(({ entry, models }, i) => (
|
|
296
|
+
<Fragment key={entry.kind}>
|
|
297
|
+
{separatesGroups(groups[i - 1]?.entry.kind, entry.kind) && <Menu.Separator />}
|
|
298
|
+
<Menu.Group>
|
|
299
|
+
{grouped && (
|
|
300
|
+
<Menu.GroupLabel className="flex items-center gap-1.5">
|
|
301
|
+
<AgentIcon kind={entry.kind} size={12} />
|
|
302
|
+
{entry.name}
|
|
303
|
+
</Menu.GroupLabel>
|
|
304
|
+
)}
|
|
305
|
+
{providerModels(entry, models)}
|
|
306
|
+
</Menu.Group>
|
|
307
|
+
</Fragment>
|
|
305
308
|
));
|
|
306
309
|
|
|
307
310
|
return (
|
|
@@ -370,16 +373,19 @@ export function RunSettings({
|
|
|
370
373
|
{found !== null && found.length === 0 && <div className="px-2.5 py-3 text-xs text-text-faint">{t('pickers.model.noMatch')}</div>}
|
|
371
374
|
{found !== null && found.length > 0 && (
|
|
372
375
|
<Menu.RadioGroup value={chosenModel} onValueChange={chooseModel}>
|
|
373
|
-
{found.map(({ entry, models }) => (
|
|
374
|
-
<
|
|
375
|
-
{
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
376
|
+
{found.map(({ entry, models }, i) => (
|
|
377
|
+
<Fragment key={entry.kind}>
|
|
378
|
+
{separatesGroups(found[i - 1]?.entry.kind, entry.kind) && <Menu.Separator />}
|
|
379
|
+
<Menu.Group>
|
|
380
|
+
{grouped && (
|
|
381
|
+
<Menu.GroupLabel className="flex items-center gap-1.5">
|
|
382
|
+
<AgentIcon kind={entry.kind} size={12} />
|
|
383
|
+
{entry.name}
|
|
384
|
+
</Menu.GroupLabel>
|
|
385
|
+
)}
|
|
386
|
+
{byMaker(entry, models)}
|
|
387
|
+
</Menu.Group>
|
|
388
|
+
</Fragment>
|
|
383
389
|
))}
|
|
384
390
|
</Menu.RadioGroup>
|
|
385
391
|
)}
|
package/src/providers/parts.tsx
CHANGED
|
@@ -10,7 +10,8 @@ const CLI_COLORS: Partial<Record<AgentKind, string>> = {
|
|
|
10
10
|
gemini: 'text-chart-gemini',
|
|
11
11
|
copilot: 'text-chart-copilot',
|
|
12
12
|
nanogpt: 'text-chart-nanogpt',
|
|
13
|
-
grok: 'text-chart-grok'
|
|
13
|
+
grok: 'text-chart-grok',
|
|
14
|
+
'anthropic-claude-api': 'text-chart-claude-api'
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
export function CliMark({ kind, size = 14, className }: { kind: AgentKind; size?: number; className?: string }) {
|
package/src/theme.css
CHANGED
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
--skill: #9333ea;
|
|
9
9
|
--skill-soft: #f7eeff;
|
|
10
10
|
/* One color per agent CLI, so a bar, a dot and a legend row all name the same provider. Apple's
|
|
11
|
-
system orange and teal
|
|
11
|
+
system orange and teal, and purple for Claude through an API key so it reads apart from Claude Code;
|
|
12
|
+
Gemini and Copilot are reserved for the day their transcripts are read. */
|
|
12
13
|
--chart-claude: #ff9500;
|
|
14
|
+
--chart-claude-api: #af52de;
|
|
13
15
|
--chart-codex: #30b0c7;
|
|
14
16
|
--chart-gemini: #3b82f6;
|
|
15
17
|
--chart-copilot: #64748b;
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
--skill: #c084fc;
|
|
38
40
|
--skill-soft: #2f2350;
|
|
39
41
|
--chart-claude: #ff9f0a;
|
|
42
|
+
--chart-claude-api: #bf5af2;
|
|
40
43
|
--chart-codex: #40c8e0;
|
|
41
44
|
--chart-gemini: #60a5fa;
|
|
42
45
|
--chart-copilot: #94a3b8;
|
|
@@ -70,6 +73,7 @@
|
|
|
70
73
|
--color-skill: var(--skill);
|
|
71
74
|
--color-skill-soft: var(--skill-soft);
|
|
72
75
|
--color-chart-claude: var(--chart-claude);
|
|
76
|
+
--color-chart-claude-api: var(--chart-claude-api);
|
|
73
77
|
--color-chart-codex: var(--chart-codex);
|
|
74
78
|
--color-chart-gemini: var(--chart-gemini);
|
|
75
79
|
--color-chart-copilot: var(--chart-copilot);
|
package/src/usage/format.ts
CHANGED
|
@@ -33,7 +33,8 @@ export const PROVIDER_LABELS: Record<UsageProvider, string> = {
|
|
|
33
33
|
codex: 'Codex',
|
|
34
34
|
nanogpt: 'NanoGPT',
|
|
35
35
|
grok: 'Grok',
|
|
36
|
-
copilot: 'GitHub Copilot'
|
|
36
|
+
copilot: 'GitHub Copilot',
|
|
37
|
+
'anthropic-claude-api': 'Claude API'
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
export const PROVIDER_COLORS: Record<UsageProvider, string> = {
|
|
@@ -41,7 +42,8 @@ export const PROVIDER_COLORS: Record<UsageProvider, string> = {
|
|
|
41
42
|
codex: 'var(--chart-codex)',
|
|
42
43
|
nanogpt: 'var(--chart-nanogpt)',
|
|
43
44
|
grok: 'var(--chart-grok)',
|
|
44
|
-
copilot: 'var(--chart-copilot)'
|
|
45
|
+
copilot: 'var(--chart-copilot)',
|
|
46
|
+
'anthropic-claude-api': 'var(--chart-claude-api)'
|
|
45
47
|
};
|
|
46
48
|
|
|
47
49
|
/*
|