@adecore/agents-react 0.21.1 → 0.22.0
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/model-requirement.d.ts +6 -0
- package/dist/agents/model-requirement.js +26 -0
- package/dist/agents/status-look.js +2 -3
- package/dist/chat/chat-client.d.ts +3 -2
- package/dist/chat/chat-client.js +4 -2
- package/dist/chat/drafts.d.ts +2 -1
- package/dist/chat/drafts.js +21 -17
- package/dist/chat/logic/ansi.js +5 -1
- package/dist/chat/logic/fork.js +8 -9
- package/dist/chat/logic/limit.js +17 -14
- package/dist/chat/logic/picker-entries.d.ts +10 -0
- package/dist/chat/logic/picker-entries.js +19 -0
- package/dist/chat/logic/resume-compaction.js +2 -11
- package/dist/chat/logic/scrubber.js +9 -18
- package/dist/chat/logic/timeline.d.ts +5 -0
- package/dist/chat/logic/timeline.js +25 -11
- package/dist/chat/logic/tool-catalog.js +3 -4
- package/dist/chat/mentions.js +5 -6
- package/dist/chat/prompt-hold.d.ts +8 -0
- package/dist/chat/prompt-hold.js +16 -0
- package/dist/chat/quote.d.ts +4 -0
- package/dist/chat/quote.js +19 -0
- package/dist/chat/runtime-modes.js +2 -4
- package/dist/chat/stash.d.ts +8 -2
- package/dist/chat/stash.js +22 -8
- package/dist/chat/subagent-list.d.ts +7 -1
- package/dist/chat/subagent-list.js +13 -1
- package/dist/chat/thumbnails.js +3 -4
- package/dist/chat/timeline-scroll.d.ts +6 -2
- package/dist/chat/timeline-scroll.js +45 -46
- package/dist/chat/ui/BookmarkSubmenu.js +1 -5
- package/dist/chat/ui/ChatActivity.js +22 -8
- package/dist/chat/ui/CodeBlock.js +2 -3
- package/dist/chat/ui/Composer.js +160 -88
- package/dist/chat/ui/ComposerInput.d.ts +3 -1
- package/dist/chat/ui/ComposerInput.js +13 -4
- package/dist/chat/ui/Markdown.js +11 -11
- package/dist/chat/ui/Pickers.js +31 -27
- package/dist/chat/ui/PromptComposer.d.ts +8 -1
- package/dist/chat/ui/PromptComposer.js +18 -6
- package/dist/chat/ui/QuoteButton.js +4 -5
- package/dist/chat/ui/RunSettings.js +8 -2
- package/dist/chat/ui/Scrubber.js +2 -3
- package/dist/chat/ui/SubagentControls.d.ts +4 -2
- package/dist/chat/ui/SubagentControls.js +13 -11
- package/dist/chat/ui/SubagentInfo.d.ts +1 -1
- package/dist/chat/ui/SubagentInfo.js +9 -15
- package/dist/chat/ui/SubagentStopButton.js +2 -1
- package/dist/chat/ui/Timeline.js +39 -21
- package/dist/chat/ui/TimelineMenu.js +3 -9
- package/dist/chat/ui/UnifiedDiff.js +3 -5
- package/dist/chat/ui/VisualFrame.js +3 -4
- package/dist/chat/ui/composer/keys.js +19 -11
- package/dist/chat/ui/composer/menu-aria.d.ts +10 -0
- package/dist/chat/ui/composer/menu-aria.js +18 -0
- package/dist/chat/ui/intelligent-ui/render-context.d.ts +1 -1
- package/dist/chat/ui/quote-selection.d.ts +5 -2
- package/dist/chat/ui/quote-selection.js +3 -2
- package/dist/chat/ui/rows/MessageRows.js +26 -8
- package/dist/chat/ui/rows/Rows.js +1 -1
- package/dist/chat/ui/rows/WorkRows.d.ts +7 -4
- package/dist/chat/ui/rows/WorkRows.js +22 -17
- package/dist/chat/visual-viewport.d.ts +1 -1
- package/dist/chat/visual-viewport.js +9 -8
- package/dist/host.d.ts +1 -0
- package/dist/host.js +1 -0
- package/dist/locales/en/agent-chat.json +30 -7
- package/dist/locales/nl/agent-chat.json +30 -7
- package/dist/port-transport.js +4 -8
- package/dist/state/chats.d.ts +2 -1
- package/dist/state/chats.js +29 -15
- package/dist/state/usage.js +44 -49
- package/dist/storage.js +7 -7
- package/dist/theme.css +6 -14
- package/dist/usage/LimitsList.js +1 -2
- package/dist/usage/UsageBreakdown.js +1 -3
- package/dist/usage/UsageDialog.js +2 -4
- package/dist/usage/format.js +6 -6
- package/dist/usage/money.js +1 -5
- package/dist/usage/summary.js +2 -4
- package/package.json +24 -4
- package/src/agents/model-requirement.ts +36 -0
- package/src/agents/status-look.ts +2 -3
- package/src/chat/chat-client.ts +7 -3
- package/src/chat/drafts.ts +33 -21
- package/src/chat/logic/ansi.ts +5 -1
- package/src/chat/logic/fork.ts +8 -9
- package/src/chat/logic/limit.ts +17 -16
- package/src/chat/logic/picker-entries.ts +25 -0
- package/src/chat/logic/resume-compaction.ts +2 -11
- package/src/chat/logic/scrubber.ts +13 -17
- package/src/chat/logic/timeline.ts +39 -13
- package/src/chat/logic/tool-catalog.ts +7 -6
- package/src/chat/mentions.ts +5 -6
- package/src/chat/prompt-hold.ts +27 -0
- package/src/chat/quote.ts +20 -0
- package/src/chat/runtime-modes.ts +2 -4
- package/src/chat/stash.ts +32 -8
- package/src/chat/subagent-list.ts +19 -5
- package/src/chat/thumbnails.ts +3 -4
- package/src/chat/timeline-scroll.ts +58 -53
- package/src/chat/ui/BookmarkSubmenu.tsx +1 -5
- package/src/chat/ui/ChatActivity.tsx +35 -9
- package/src/chat/ui/CodeBlock.tsx +2 -3
- package/src/chat/ui/Composer.tsx +263 -138
- package/src/chat/ui/ComposerInput.tsx +18 -3
- package/src/chat/ui/Markdown.tsx +13 -17
- package/src/chat/ui/Pickers.tsx +56 -39
- package/src/chat/ui/PromptComposer.tsx +37 -8
- package/src/chat/ui/QuoteButton.tsx +5 -5
- package/src/chat/ui/RunSettings.tsx +9 -2
- package/src/chat/ui/Scrubber.tsx +2 -3
- package/src/chat/ui/SubagentControls.tsx +23 -22
- package/src/chat/ui/SubagentInfo.tsx +24 -42
- package/src/chat/ui/SubagentStopButton.tsx +2 -1
- package/src/chat/ui/SubagentTimeline.tsx +1 -2
- package/src/chat/ui/Timeline.tsx +44 -24
- package/src/chat/ui/TimelineMenu.tsx +3 -9
- package/src/chat/ui/UnifiedDiff.tsx +3 -5
- package/src/chat/ui/VisualFrame.tsx +3 -4
- package/src/chat/ui/composer/keys.ts +21 -11
- package/src/chat/ui/composer/menu-aria.ts +29 -0
- package/src/chat/ui/intelligent-ui/render-context.ts +2 -2
- package/src/chat/ui/quote-selection.ts +6 -4
- package/src/chat/ui/rehype-chips.ts +1 -1
- package/src/chat/ui/rehype-fade.ts +1 -1
- package/src/chat/ui/remark-html-as-text.ts +1 -1
- package/src/chat/ui/rows/MessageRows.tsx +47 -9
- package/src/chat/ui/rows/Rows.tsx +3 -1
- package/src/chat/ui/rows/WorkRows.tsx +101 -70
- package/src/chat/visual-viewport.ts +10 -8
- package/src/host.ts +4 -3
- package/src/locales/en/agent-chat.json +30 -7
- package/src/locales/nl/agent-chat.json +30 -7
- package/src/port-transport.ts +4 -8
- package/src/state/chats.ts +42 -16
- package/src/state/usage.ts +49 -60
- package/src/storage.ts +7 -7
- package/src/theme.css +6 -14
- package/src/usage/LimitsList.tsx +2 -4
- package/src/usage/UsageBreakdown.tsx +2 -5
- package/src/usage/UsageDialog.tsx +2 -4
- package/src/usage/format.ts +6 -6
- package/src/usage/money.ts +1 -5
- package/src/usage/summary.ts +2 -4
|
@@ -91,7 +91,8 @@
|
|
|
91
91
|
"user": {
|
|
92
92
|
"heading": "Jij",
|
|
93
93
|
"showAll": "Alles tonen",
|
|
94
|
-
"showLess": "Minder tonen"
|
|
94
|
+
"showLess": "Minder tonen",
|
|
95
|
+
"quoteGone": "Het antwoord waar dit citaat vandaan kwam, staat niet meer in deze chat."
|
|
95
96
|
},
|
|
96
97
|
"report": {
|
|
97
98
|
"heading": "Rapport"
|
|
@@ -107,7 +108,8 @@
|
|
|
107
108
|
"note": {
|
|
108
109
|
"hide": "Verbergen",
|
|
109
110
|
"show": "Tonen",
|
|
110
|
-
"openFork": "Fork openen"
|
|
111
|
+
"openFork": "Fork openen",
|
|
112
|
+
"openWaiting": "Openen om te antwoorden"
|
|
111
113
|
},
|
|
112
114
|
"compaction": {
|
|
113
115
|
"plain": "Context gecomprimeerd",
|
|
@@ -165,6 +167,9 @@
|
|
|
165
167
|
},
|
|
166
168
|
"changedFiles_one": "{{count}} gewijzigd bestand",
|
|
167
169
|
"changedFiles_other": "{{count}} gewijzigde bestanden",
|
|
170
|
+
"folderChanges_one": "{{count}} wijziging in de map tijdens deze beurt",
|
|
171
|
+
"folderChanges_other": "{{count}} wijzigingen in de map tijdens deze beurt",
|
|
172
|
+
"baseMoved": "De branch is tijdens deze beurt verplaatst ({{from}} naar {{to}}), dus dit omvat ook wat daarmee binnenkwam.",
|
|
168
173
|
"andMore": "en meer, afgekapt",
|
|
169
174
|
"edits_one": "{{count}} bewerking",
|
|
170
175
|
"edits_other": "{{count}} bewerkingen",
|
|
@@ -249,6 +254,17 @@
|
|
|
249
254
|
},
|
|
250
255
|
"composer": {
|
|
251
256
|
"slotFailed": "Dit onderdeel kon niet worden getekend",
|
|
257
|
+
"inputLabel": "Bericht",
|
|
258
|
+
"menu": {
|
|
259
|
+
"commands": "Commando's",
|
|
260
|
+
"skills": "Skills",
|
|
261
|
+
"mentions": "Vermeldingen"
|
|
262
|
+
},
|
|
263
|
+
"held": {
|
|
264
|
+
"question": "Er wacht een vraag. Die opent zodra je even stopt met typen.",
|
|
265
|
+
"approval": "Er wacht een goedkeuring. Die opent zodra je even stopt met typen.",
|
|
266
|
+
"show": "Nu tonen"
|
|
267
|
+
},
|
|
252
268
|
"commands": {
|
|
253
269
|
"model": "Wissel van model",
|
|
254
270
|
"compact": "Comprimeer de context",
|
|
@@ -294,7 +310,8 @@
|
|
|
294
310
|
},
|
|
295
311
|
"quote": {
|
|
296
312
|
"add": "Citeren",
|
|
297
|
-
"remove": "Citaat verwijderen"
|
|
313
|
+
"remove": "Citaat verwijderen",
|
|
314
|
+
"goToSource": "Naar het antwoord"
|
|
298
315
|
},
|
|
299
316
|
"removeAttachment": "{{name}} verwijderen",
|
|
300
317
|
"attach": "Bestanden toevoegen",
|
|
@@ -319,6 +336,9 @@
|
|
|
319
336
|
"monitors_one": "{{count}} monitor",
|
|
320
337
|
"monitors_other": "{{count}} monitors",
|
|
321
338
|
"pausedUntil": "gepauzeerd tot {{time}}",
|
|
339
|
+
"progress": "{{done}} van {{total}} sub-agents klaar",
|
|
340
|
+
"needsYou_one": "{{count}} vraagt aandacht",
|
|
341
|
+
"needsYou_other": "{{count}} vragen aandacht",
|
|
322
342
|
"took": {
|
|
323
343
|
"done": "klaar in {{duration}}",
|
|
324
344
|
"failed": "mislukt na {{duration}}",
|
|
@@ -332,8 +352,10 @@
|
|
|
332
352
|
"subagents": {
|
|
333
353
|
"stop": {
|
|
334
354
|
"task": "Deze taak stoppen",
|
|
355
|
+
"native": "Deze sub-agent stoppen",
|
|
335
356
|
"mark": "Markeren als gestopt. De CLI kan een losse sub-agent niet stoppen, dus die werkt mogelijk door tot het proces van de chat eindigt."
|
|
336
357
|
},
|
|
358
|
+
"stale": "Deze sub-agent hoort bij een proces dat al gestopt is.",
|
|
337
359
|
"title": "Sub-agents",
|
|
338
360
|
"backToMain": "Terug naar de main agent",
|
|
339
361
|
"loading": "Gesprek laden…",
|
|
@@ -344,9 +366,7 @@
|
|
|
344
366
|
"stopFailed": "De sub-agent kon niet worden gestopt",
|
|
345
367
|
"info": {
|
|
346
368
|
"label": "Over deze sub-agent",
|
|
347
|
-
"tokens": "{{tokens}} tokens"
|
|
348
|
-
"showTask": "Opdracht tonen",
|
|
349
|
-
"hideTask": "Opdracht verbergen"
|
|
369
|
+
"tokens": "{{tokens}} tokens"
|
|
350
370
|
}
|
|
351
371
|
},
|
|
352
372
|
"modes": {
|
|
@@ -382,7 +402,10 @@
|
|
|
382
402
|
"noMatch": "Geen modellen gevonden",
|
|
383
403
|
"legacyGroup_one": "Legacy-modellen ({{count}})",
|
|
384
404
|
"legacyGroup_other": "Legacy-modellen ({{count}})",
|
|
385
|
-
"legacy": "Legacy"
|
|
405
|
+
"legacy": "Legacy",
|
|
406
|
+
"requires": "Vereist {{cli}} {{version}} of nieuwer op {{machine}}",
|
|
407
|
+
"requiresHere": "Vereist {{cli}} {{version}} of nieuwer",
|
|
408
|
+
"providerSettings": "Providerinstellingen"
|
|
386
409
|
},
|
|
387
410
|
"stash": {
|
|
388
411
|
"title": "Stashed prompts",
|
package/dist/port-transport.js
CHANGED
|
@@ -93,15 +93,11 @@ export function portTransport(port) {
|
|
|
93
93
|
return promise;
|
|
94
94
|
},
|
|
95
95
|
on(event, handler) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
eventHandlers.set(event, handlers);
|
|
100
|
-
}
|
|
101
|
-
const set = handlers;
|
|
102
|
-
set.add(handler);
|
|
96
|
+
const handlers = eventHandlers.get(event) ?? new Set();
|
|
97
|
+
eventHandlers.set(event, handlers);
|
|
98
|
+
handlers.add(handler);
|
|
103
99
|
return () => {
|
|
104
|
-
|
|
100
|
+
handlers.delete(handler);
|
|
105
101
|
};
|
|
106
102
|
},
|
|
107
103
|
subscribeStatus(handler) {
|
package/dist/state/chats.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChatApprovalItem, ChatBookmark, ChatEvent, ChatHistoryResult, ChatInfo, ChatItem, ChatQuestionItem, ChatVisual } from '@adecore/agent-contracts';
|
|
1
|
+
import type { AgentKind, ChatApprovalItem, ChatBookmark, ChatEvent, ChatHistoryResult, ChatInfo, ChatItem, ChatQuestionItem, ChatVisual } from '@adecore/agent-contracts';
|
|
2
2
|
export interface ChatState {
|
|
3
3
|
info: ChatInfo;
|
|
4
4
|
items: Record<string, ChatItem>;
|
|
@@ -43,5 +43,6 @@ export declare function applyEvent(state: ChatState, event: ChatEvent): ChatStat
|
|
|
43
43
|
export declare const useChats: import("zustand").UseBoundStore<import("zustand").StoreApi<ChatsStore>>;
|
|
44
44
|
export declare function chatSink(keyOf: (chatId: string) => string): ChatSink;
|
|
45
45
|
export declare function useChatRow<T>(chatId: string, select: (row: ChatState | undefined) => T): T;
|
|
46
|
+
export declare function useReportedModels(provider: AgentKind): ReadonlySet<string>;
|
|
46
47
|
export declare function useCurrentItem<T extends ChatItem>(chatId: string, derived: T): T;
|
|
47
48
|
export {};
|
package/dist/state/chats.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { useContext, useMemo } from 'react';
|
|
1
2
|
import { create } from 'zustand';
|
|
2
|
-
import { useChatScope } from '../scope.js';
|
|
3
|
+
import { ChatScopeContext, useChatScope } from '../scope.js';
|
|
3
4
|
function isWaiting(item) {
|
|
4
5
|
return (item?.kind === 'approval' && item.decision === 'pending') || (item?.kind === 'question' && item.state === 'pending');
|
|
5
6
|
}
|
|
@@ -113,6 +114,14 @@ export function applyEvent(state, event) {
|
|
|
113
114
|
return stateOf(event.info, event.items);
|
|
114
115
|
}
|
|
115
116
|
}
|
|
117
|
+
/* Fields of a held chat that are not part of its thread; a chat this client does not hold stays as it is. */
|
|
118
|
+
function withFields(store, key, fields) {
|
|
119
|
+
const current = store.byKey[key];
|
|
120
|
+
if (!current) {
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
return { byKey: { ...store.byKey, [key]: { ...current, ...fields } } };
|
|
124
|
+
}
|
|
116
125
|
export const useChats = create((set) => ({
|
|
117
126
|
byKey: {},
|
|
118
127
|
statusByKey: {},
|
|
@@ -166,22 +175,10 @@ export const useChats = create((set) => ({
|
|
|
166
175
|
});
|
|
167
176
|
},
|
|
168
177
|
bookmarks(key, bookmarks) {
|
|
169
|
-
set((s) => {
|
|
170
|
-
const current = s.byKey[key];
|
|
171
|
-
if (!current) {
|
|
172
|
-
return {};
|
|
173
|
-
}
|
|
174
|
-
return { byKey: { ...s.byKey, [key]: { ...current, bookmarks } } };
|
|
175
|
-
});
|
|
178
|
+
set((s) => withFields(s, key, { bookmarks }));
|
|
176
179
|
},
|
|
177
180
|
visuals(key, visuals) {
|
|
178
|
-
set((s) => {
|
|
179
|
-
const current = s.byKey[key];
|
|
180
|
-
if (!current) {
|
|
181
|
-
return {};
|
|
182
|
-
}
|
|
183
|
-
return { byKey: { ...s.byKey, [key]: { ...current, visuals } } };
|
|
184
|
-
});
|
|
181
|
+
set((s) => withFields(s, key, { visuals }));
|
|
185
182
|
},
|
|
186
183
|
forget(key) {
|
|
187
184
|
set((s) => {
|
|
@@ -213,6 +210,23 @@ export function useChatRow(chatId, select) {
|
|
|
213
210
|
const { keyOf } = useChatScope();
|
|
214
211
|
return useChats((s) => select(s.byKey[keyOf(chatId)]));
|
|
215
212
|
}
|
|
213
|
+
/*
|
|
214
|
+
* The models the CLI of this provider reported running in the chats this client holds of the host.
|
|
215
|
+
* A model it ran is proof the CLI offers it, whatever the version says. Outside a scope there is none.
|
|
216
|
+
*/
|
|
217
|
+
export function useReportedModels(provider) {
|
|
218
|
+
const scope = useContext(ChatScopeContext);
|
|
219
|
+
const joined = useChats((s) => {
|
|
220
|
+
const names = new Set();
|
|
221
|
+
for (const [key, state] of Object.entries(s.statusByKey)) {
|
|
222
|
+
if (scope?.owns(key) === true && state.info.provider === provider && state.info.model !== null) {
|
|
223
|
+
names.add(state.info.model);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return [...names].sort().join('\n');
|
|
227
|
+
});
|
|
228
|
+
return useMemo(() => new Set(joined === '' ? [] : joined.split('\n')), [joined]);
|
|
229
|
+
}
|
|
216
230
|
/* The item as the thread holds it now, for a row derived from the structure, which a delta leaves alone. */
|
|
217
231
|
export function useCurrentItem(chatId, derived) {
|
|
218
232
|
return useChatRow(chatId, (row) => {
|
package/dist/state/usage.js
CHANGED
|
@@ -32,12 +32,6 @@ function parsePreferences(raw) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
const storage = persistedJson(storageKey, parsePreferences, DEFAULTS, () => chatStorageLegacyKeys('usage'));
|
|
35
|
-
function readPreferences() {
|
|
36
|
-
return storage.read();
|
|
37
|
-
}
|
|
38
|
-
function persist(preferences) {
|
|
39
|
-
storage.write(preferences);
|
|
40
|
-
}
|
|
41
35
|
/* The three stored choices out of the store, so a setter writes the other two back unchanged. */
|
|
42
36
|
function chosen(state) {
|
|
43
37
|
return { period: state.period, metric: state.metric, currency: state.currency };
|
|
@@ -49,10 +43,7 @@ function pad(value) {
|
|
|
49
43
|
export function dayOf(date) {
|
|
50
44
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
51
45
|
}
|
|
52
|
-
/*
|
|
53
|
-
* What a period asks for. Today counts from local midnight in hours, the way the commit log already
|
|
54
|
-
* groups days, so every other period reads as one bar per calendar day.
|
|
55
|
-
*/
|
|
46
|
+
/* What a period asks for: today in hours from local midnight, every other period a bar per calendar day. */
|
|
56
47
|
export function windowFor(period, now = new Date()) {
|
|
57
48
|
const days = USAGE_PERIODS.find((entry) => entry.id === period)?.days ?? 7;
|
|
58
49
|
const from = new Date(now.getFullYear(), now.getMonth(), now.getDate() - (days - 1));
|
|
@@ -75,46 +66,50 @@ export function askedKey(payload) {
|
|
|
75
66
|
const EMPTY = { asked: null, summary: null, loading: false, failed: false, limits: null };
|
|
76
67
|
/* Reads the period, metric and currency again, once another window of the same origin wrote them. */
|
|
77
68
|
export function reloadUsagePreferences() {
|
|
78
|
-
useUsageStore.setState(
|
|
69
|
+
useUsageStore.setState(storage.read());
|
|
79
70
|
}
|
|
80
|
-
export const useUsageStore = createChatStore((set, get) =>
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
71
|
+
export const useUsageStore = createChatStore((set, get) => {
|
|
72
|
+
const choosePreference = (change) => {
|
|
73
|
+
storage.write({ ...chosen(get()), ...change });
|
|
74
|
+
set(change);
|
|
75
|
+
};
|
|
76
|
+
const patchRow = (scopeId, change) => {
|
|
77
|
+
set({ byScope: { ...get().byScope, [scopeId]: { ...(get().byScope[scopeId] ?? EMPTY), ...change } } });
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
...DEFAULTS,
|
|
81
|
+
byScope: {},
|
|
82
|
+
chosen: null,
|
|
83
|
+
choose(scopeId) {
|
|
84
|
+
set({ chosen: scopeId });
|
|
85
|
+
},
|
|
86
|
+
setPeriod(period) {
|
|
87
|
+
choosePreference({ period });
|
|
88
|
+
},
|
|
89
|
+
setMetric(metric) {
|
|
90
|
+
choosePreference({ metric });
|
|
91
|
+
},
|
|
92
|
+
setCurrency(currency) {
|
|
93
|
+
choosePreference({ currency });
|
|
94
|
+
},
|
|
95
|
+
setLoading(scopeId, loading) {
|
|
96
|
+
patchRow(scopeId, { loading });
|
|
97
|
+
},
|
|
98
|
+
receive(scopeId, asked, summary) {
|
|
99
|
+
patchRow(scopeId, { asked, summary, loading: false, failed: false });
|
|
100
|
+
},
|
|
101
|
+
fail(scopeId) {
|
|
102
|
+
patchRow(scopeId, { loading: false, failed: true });
|
|
103
|
+
},
|
|
104
|
+
setLimits(scopeId, limits) {
|
|
105
|
+
patchRow(scopeId, { limits });
|
|
106
|
+
},
|
|
107
|
+
forget(scopeId) {
|
|
108
|
+
const { [scopeId]: _gone, ...rest } = get().byScope;
|
|
109
|
+
set({ byScope: rest });
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}, (store) => store.setState(storage.read()));
|
|
118
113
|
export function useUsage(select) {
|
|
119
114
|
const { id } = useChatScope();
|
|
120
115
|
return useUsageStore((s) => select({ period: s.period, metric: s.metric, currency: s.currency, ...(s.byScope[id] ?? EMPTY) }));
|
package/dist/storage.js
CHANGED
|
@@ -64,25 +64,25 @@ export function createChatStore(initial, hydrate) {
|
|
|
64
64
|
hydrate(store);
|
|
65
65
|
};
|
|
66
66
|
hydrators.push(hydrateOnce);
|
|
67
|
-
const
|
|
67
|
+
const ready = () => {
|
|
68
68
|
hydrateChatStorage();
|
|
69
69
|
hydrateOnce();
|
|
70
|
+
};
|
|
71
|
+
const useStore = ((...args) => {
|
|
72
|
+
ready();
|
|
70
73
|
return store(...args);
|
|
71
74
|
});
|
|
72
75
|
Object.assign(useStore, store);
|
|
73
76
|
useStore.getState = () => {
|
|
74
|
-
|
|
75
|
-
hydrateOnce();
|
|
77
|
+
ready();
|
|
76
78
|
return store.getState();
|
|
77
79
|
};
|
|
78
80
|
useStore.subscribe = (...args) => {
|
|
79
|
-
|
|
80
|
-
hydrateOnce();
|
|
81
|
+
ready();
|
|
81
82
|
return store.subscribe(...args);
|
|
82
83
|
};
|
|
83
84
|
useStore.setState = ((...args) => {
|
|
84
|
-
|
|
85
|
-
hydrateOnce();
|
|
85
|
+
ready();
|
|
86
86
|
store.setState(...args);
|
|
87
87
|
});
|
|
88
88
|
return useStore;
|
package/dist/theme.css
CHANGED
|
@@ -76,8 +76,6 @@
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
@layer components {
|
|
79
|
-
/* ---------------------------------------------------------------- Chat */
|
|
80
|
-
|
|
81
79
|
/* Text in a chat is there to be read and copied, so the thread selects even though the app does
|
|
82
80
|
not. Its chrome stays out of it: a drag on a fold header or a chip would select the row.
|
|
83
81
|
The pretty wrap from `body` would be recomputed on the growing paragraph every frame a reply
|
|
@@ -160,18 +158,12 @@
|
|
|
160
158
|
}
|
|
161
159
|
|
|
162
160
|
/*
|
|
163
|
-
* Markdown, outside every layer on purpose
|
|
164
|
-
* and
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
* Markdown anywhere in the app: the chat timeline, a note node and the file preview all render
|
|
170
|
-
* the same `Markdown` component, which carries `prose prose-sm max-w-none text-sm` next to this
|
|
171
|
-
* class. Prose brings the rhythm; everything here is what the app decides instead of the plugin.
|
|
172
|
-
* The semantic tokens flip with the theme on their own, so the prose variables read from them
|
|
173
|
-
* and `prose-invert` is a second source of truth the app does not need. The size comes from the
|
|
174
|
-
* `text-sm` utility, which a node, a view and the file preview each move.
|
|
161
|
+
* Markdown, outside every layer on purpose: the typography plugin registers `.prose` as a utility,
|
|
162
|
+
* and only unlayered styles are sure to land on top of it.
|
|
163
|
+
*
|
|
164
|
+
* Every `Markdown` carries `prose prose-sm max-w-none text-sm` next to this class. Prose brings the
|
|
165
|
+
* rhythm; everything here is what the app decides instead. The semantic tokens flip with the theme on
|
|
166
|
+
* their own, so the prose variables read from them and `prose-invert` is not needed.
|
|
175
167
|
*/
|
|
176
168
|
.prose.chat-markdown {
|
|
177
169
|
--tw-prose-body: var(--text);
|
package/dist/usage/LimitsList.js
CHANGED
|
@@ -9,8 +9,7 @@ import { formatClock, formatWeekdayClock, isSameDay, formatCountdown, formatPerc
|
|
|
9
9
|
import { ProviderLogo } from '../agents/ProviderLogo.js';
|
|
10
10
|
import { PROVIDER_COLORS, PROVIDER_LABELS } from './format.js';
|
|
11
11
|
import { accountNote, explain, isSignedOut, nextReset } from './limit-groups.js';
|
|
12
|
-
/* Red where a window is nearly spent, amber where it is worth knowing
|
|
13
|
-
is not news, so it takes the text color rather than a hue that competes with the two that are. */
|
|
12
|
+
/* Red where a window is nearly spent, amber where it is worth knowing; room to spare is not news and takes the text color. */
|
|
14
13
|
function toneOf(used) {
|
|
15
14
|
return used >= 0.9 ? 'bg-status-error' : used >= 0.7 ? 'bg-status-needs-you' : 'bg-text';
|
|
16
15
|
}
|
|
@@ -12,11 +12,9 @@ import { modelNameFromSlug } from '../agents/model-name.js';
|
|
|
12
12
|
import { formatCount, formatTokens, PROVIDER_COLORS, PROVIDER_LABELS, shortPath, slotLabel } from './format.js';
|
|
13
13
|
import { useMoney } from './money.js';
|
|
14
14
|
import { deriveDays } from './summary.js';
|
|
15
|
-
/* The row of every table, the same height and the same hover as a commit row in the git panel. */
|
|
16
15
|
const ROW = 'flex h-8 items-center gap-2 rounded-md px-2 text-xs hover:bg-surface-hover';
|
|
17
16
|
const HEAD = 'flex h-6 items-center gap-2 px-2 text-xs text-text-faint';
|
|
18
|
-
/*
|
|
19
|
-
again. The first column then starts on the same line as every other section of the page. */
|
|
17
|
+
/* The table pulls the padding that gives a row's hover room back off, so its first column lines up with the page. */
|
|
20
18
|
const TABLE = '-mx-2 flex flex-col';
|
|
21
19
|
const TABS = ['models', 'projects', 'day'];
|
|
22
20
|
/* A share of the biggest row, never under one pixel. A row that did something has to be visible. */
|
|
@@ -2,10 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import i18next from 'i18next';
|
|
3
3
|
import { Dialog } from '@adecore/ui';
|
|
4
4
|
/*
|
|
5
|
-
* The frame of the usage page
|
|
6
|
-
*
|
|
7
|
-
* open, so nothing is scanned behind a closed dialog. It is a dialog and not a view, since none of it
|
|
8
|
-
* belongs to one project.
|
|
5
|
+
* The frame of the usage page, wider than the settings for the chart and the breakdown. What goes in
|
|
6
|
+
* it mounts only while it is open, so nothing is scanned behind a closed dialog.
|
|
9
7
|
*/
|
|
10
8
|
export function UsageDialog({ open, onOpenChange, children }) {
|
|
11
9
|
return (_jsx(Dialog.Root, { open: open, onOpenChange: onOpenChange, children: _jsxs(Dialog.Popup, { className: "flex h-[820px] w-[1080px] flex-col", children: [children, _jsx(Dialog.Description, { className: "sr-only", children: i18next.t('agent-usage:dialog.description') })] }) }));
|
package/dist/usage/format.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { formatDay, formatHour, formatWeekdayDay, formatMoney, formatNumber, formatTokens } from '@adecore/ui/format';
|
|
2
2
|
export { formatClock } from '@adecore/ui/format';
|
|
3
|
-
/*
|
|
4
|
-
would be: `$5,480.96` in the US, `$ 5.480,96` in the Netherlands. The labels stay English. */
|
|
3
|
+
/* Read in the region of the machine looking at it: `$5,480.96` in the US, `$ 5.480,96` in the Netherlands. */
|
|
5
4
|
export function formatCount(value) {
|
|
6
5
|
return formatNumber(value);
|
|
7
6
|
}
|
|
@@ -23,8 +22,10 @@ export function moneyFormat(currency, rate) {
|
|
|
23
22
|
}
|
|
24
23
|
export const PROVIDER_LABELS = { claude: 'Claude Code', codex: 'Codex' };
|
|
25
24
|
export const PROVIDER_COLORS = { claude: 'var(--chart-claude)', codex: 'var(--chart-codex)' };
|
|
26
|
-
/*
|
|
27
|
-
|
|
25
|
+
/*
|
|
26
|
+
* A slot is `2026-09-10` or `2026-09-10T14`, already in the viewer's own zone, so it is read as plain
|
|
27
|
+
* wall clock and never handed to a parser that would shift it back.
|
|
28
|
+
*/
|
|
28
29
|
function dateOfSlot(slot) {
|
|
29
30
|
return new Date(Number(slot.slice(0, 4)), Number(slot.slice(5, 7)) - 1, Number(slot.slice(8, 10)));
|
|
30
31
|
}
|
|
@@ -47,8 +48,7 @@ export function slotAxisLabel(slot) {
|
|
|
47
48
|
export function formatDate(at) {
|
|
48
49
|
return formatDay(at);
|
|
49
50
|
}
|
|
50
|
-
/*
|
|
51
|
-
same repository apart, without the home directory nobody needs to read again. */
|
|
51
|
+
/* Enough of a path's tail to tell two checkouts of the same repository apart, under a row that already carries the name. */
|
|
52
52
|
export function shortPath(path) {
|
|
53
53
|
const parts = path.split('/').filter(Boolean);
|
|
54
54
|
return parts.length <= 3 ? path : `…/${parts.slice(-3).join('/')}`;
|
package/dist/usage/money.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { useUsage } from '../state/usage.js';
|
|
3
3
|
import { moneyFormat } from './format.js';
|
|
4
|
-
/*
|
|
5
|
-
* The formatter every amount on the page goes through: the currency that was chosen, at the rate
|
|
6
|
-
* the summary on screen carries. It is a hook rather than a prop because every row wants it and
|
|
7
|
-
* none of them wants to know where the rate came from.
|
|
8
|
-
*/
|
|
4
|
+
/* The formatter every amount on the page goes through: the chosen currency, at the rate the summary on screen carries. */
|
|
9
5
|
export function useMoney() {
|
|
10
6
|
const currency = useUsage((s) => s.currency);
|
|
11
7
|
const rate = useUsage((s) => s.summary?.rate ?? null);
|
package/dist/usage/summary.js
CHANGED
|
@@ -74,10 +74,8 @@ export function deriveUsage(summary, metric) {
|
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
/*
|
|
77
|
-
* The
|
|
78
|
-
*
|
|
79
|
-
* happened in is left out, since the chart already shows the gap, and a quiet fortnight would otherwise
|
|
80
|
-
* be fourteen rows of zeroes between the days worth reading.
|
|
77
|
+
* The chart's buckets as a table of calendar days, newest first; an hour slot folds onto the date it
|
|
78
|
+
* names. A day nothing happened in is left out, since the chart already shows the gap.
|
|
81
79
|
*/
|
|
82
80
|
export function deriveDays(summary) {
|
|
83
81
|
const rows = new Map();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "React agent chat threads, composers, approvals, provider accounts and usage views.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -34,6 +34,11 @@
|
|
|
34
34
|
"types": "./dist/agents/accounts.d.ts",
|
|
35
35
|
"default": "./dist/agents/accounts.js"
|
|
36
36
|
},
|
|
37
|
+
"./agents/model-requirement": {
|
|
38
|
+
"source": "./src/agents/model-requirement.ts",
|
|
39
|
+
"types": "./dist/agents/model-requirement.d.ts",
|
|
40
|
+
"default": "./dist/agents/model-requirement.js"
|
|
41
|
+
},
|
|
37
42
|
"./agents/model-name": {
|
|
38
43
|
"source": "./src/agents/model-name.ts",
|
|
39
44
|
"types": "./dist/agents/model-name.d.ts",
|
|
@@ -104,6 +109,11 @@
|
|
|
104
109
|
"types": "./dist/chat/guards.d.ts",
|
|
105
110
|
"default": "./dist/chat/guards.js"
|
|
106
111
|
},
|
|
112
|
+
"./chat/logic/picker-entries": {
|
|
113
|
+
"source": "./src/chat/logic/picker-entries.ts",
|
|
114
|
+
"types": "./dist/chat/logic/picker-entries.d.ts",
|
|
115
|
+
"default": "./dist/chat/logic/picker-entries.js"
|
|
116
|
+
},
|
|
107
117
|
"./chat/logic/ansi": {
|
|
108
118
|
"source": "./src/chat/logic/ansi.ts",
|
|
109
119
|
"types": "./dist/chat/logic/ansi.d.ts",
|
|
@@ -219,6 +229,11 @@
|
|
|
219
229
|
"types": "./dist/chat/preferences.d.ts",
|
|
220
230
|
"default": "./dist/chat/preferences.js"
|
|
221
231
|
},
|
|
232
|
+
"./chat/prompt-hold": {
|
|
233
|
+
"source": "./src/chat/prompt-hold.ts",
|
|
234
|
+
"types": "./dist/chat/prompt-hold.d.ts",
|
|
235
|
+
"default": "./dist/chat/prompt-hold.js"
|
|
236
|
+
},
|
|
222
237
|
"./chat/quote": {
|
|
223
238
|
"source": "./src/chat/quote.ts",
|
|
224
239
|
"types": "./dist/chat/quote.d.ts",
|
|
@@ -494,6 +509,11 @@
|
|
|
494
509
|
"types": "./dist/chat/ui/composer/keys.d.ts",
|
|
495
510
|
"default": "./dist/chat/ui/composer/keys.js"
|
|
496
511
|
},
|
|
512
|
+
"./chat/ui/composer/menu-aria": {
|
|
513
|
+
"source": "./src/chat/ui/composer/menu-aria.ts",
|
|
514
|
+
"types": "./dist/chat/ui/composer/menu-aria.d.ts",
|
|
515
|
+
"default": "./dist/chat/ui/composer/menu-aria.js"
|
|
516
|
+
},
|
|
497
517
|
"./chat/ui/diff-theme": {
|
|
498
518
|
"source": "./src/chat/ui/diff-theme.ts",
|
|
499
519
|
"types": "./dist/chat/ui/diff-theme.d.ts",
|
|
@@ -1011,8 +1031,8 @@
|
|
|
1011
1031
|
"test:visuals": "bun --config=integration.bunfig.toml --conditions=source test ./src/chat/visual-viewport.integration.test.ts"
|
|
1012
1032
|
},
|
|
1013
1033
|
"dependencies": {
|
|
1014
|
-
"@adecore/agent-contracts": "0.
|
|
1015
|
-
"@adecore/intelligent-ui": "0.
|
|
1034
|
+
"@adecore/agent-contracts": "0.22.0",
|
|
1035
|
+
"@adecore/intelligent-ui": "0.22.0",
|
|
1016
1036
|
"@codemirror/commands": "^6.11.1",
|
|
1017
1037
|
"@codemirror/language": "^6.12.4",
|
|
1018
1038
|
"@codemirror/state": "^6.7.6",
|
|
@@ -1033,7 +1053,7 @@
|
|
|
1033
1053
|
"zustand": "^5.0.15"
|
|
1034
1054
|
},
|
|
1035
1055
|
"peerDependencies": {
|
|
1036
|
-
"@adecore/ui": "^0.
|
|
1056
|
+
"@adecore/ui": "^0.22.0",
|
|
1037
1057
|
"i18next": "^26.4.2",
|
|
1038
1058
|
"react": "^19.3.0",
|
|
1039
1059
|
"react-dom": "^19.3.0",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ModelInfo, ProviderInfo } from '@adecore/agent-contracts';
|
|
2
|
+
|
|
3
|
+
export interface ModelRequirement {
|
|
4
|
+
/* The CLI's name, as the provider list gives it. */
|
|
5
|
+
cli: string;
|
|
6
|
+
minVersion: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function partsOf(version: string, strict: boolean): number[] | null {
|
|
10
|
+
const found = (strict ? /^(\d+)\.(\d+)(?:\.(\d+))?$/ : /(\d+)\.(\d+)\.(\d+)/).exec(version);
|
|
11
|
+
return found === null ? null : [Number(found[1]), Number(found[2]), Number(found[3] ?? 0)];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* Whether the model's reported name is this model: its slug, the slug with a suffix such as `[1m]`. */
|
|
15
|
+
function isReported(slug: string, reported: ReadonlySet<string>): boolean {
|
|
16
|
+
return [...reported].some((name) => name === slug || name.startsWith(`${slug}[`));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* What a model asks of the CLI that is too old for it, or null when nothing blocks it: no minimum is
|
|
21
|
+
* known, the CLI's version is not a readable x.y.z (so an unknown version invents no requirement), the
|
|
22
|
+
* CLI is new enough, or a chat of this provider already reported running the model.
|
|
23
|
+
*/
|
|
24
|
+
export function modelRequirementOf(model: ModelInfo, provider: ProviderInfo, reported: ReadonlySet<string>): ModelRequirement | null {
|
|
25
|
+
const minimum = model.minCliVersion === undefined ? null : partsOf(model.minCliVersion, true);
|
|
26
|
+
const installed = provider.version === null ? null : partsOf(provider.version, false);
|
|
27
|
+
if (minimum === null || installed === null || isReported(model.slug, reported)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
for (let i = 0; i < 3; i++) {
|
|
31
|
+
if (installed[i] !== minimum[i]) {
|
|
32
|
+
return (installed[i] ?? 0) > (minimum[i] ?? 0) ? null : { cli: provider.name, minVersion: model.minCliVersion ?? '' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
@@ -10,9 +10,8 @@ export interface StatusLook {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/*
|
|
13
|
-
* One state, one mark
|
|
14
|
-
*
|
|
15
|
-
* motion with every other animation (`styles.css`).
|
|
13
|
+
* One state, one mark, wherever work is drawn: a sub-agent entry, a task, a summary or a toast. A
|
|
14
|
+
* spinner stops under reduced motion with every other animation.
|
|
16
15
|
*/
|
|
17
16
|
const LOOKS: Record<StatusWord, StatusLook> = {
|
|
18
17
|
running: { icon: LoaderCircle, tone: 'text-status-running', spins: true },
|