@ykurilov/agent-chat-react 0.70.1 → 0.71.1
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/CHANGELOG.md +20 -0
- package/dist/{chunk-Z7X5D4OF.js → chunk-WJJY2WLQ.js} +98 -46
- package/dist/chunk-WJJY2WLQ.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/panel.js +1 -1
- package/dist/types/agent-chat-extensions.d.ts +2 -0
- package/dist/types/agent-chat.d.ts +2 -0
- package/dist/types/chat-types.d.ts +1 -0
- package/dist/types/composer-options.d.ts +30 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/labels.d.ts +24 -1
- package/dist/types/skin-contract.d.ts +26 -2
- package/dist/types/work-view/work-layout.d.ts +1 -0
- package/package.json +1 -1
- package/dist/chunk-Z7X5D4OF.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @ykurilov/agent-chat-react
|
|
2
2
|
|
|
3
|
+
## 0.71.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 519914e: Лента закрепляет только сообщения у текущего окна, пока следует за ответом. При расхождении измеренных высот DOM и оценок виртуального списка больше не монтируется весь остаток длинной истории. Растущий ответ и черновик правки сохраняют отдельное закрепление.
|
|
8
|
+
|
|
9
|
+
Прилипание к низу сохраняется, когда пересчёт высот сдвигает сообщение и прокрутку на одинаковое расстояние вверх, даже при росте списка. Ввод читателя вверх по-прежнему останавливает следование за ответом.
|
|
10
|
+
|
|
11
|
+
Служебные обёртки сообщений не анимируют координаты: глобальное правило уменьшенного движения с ненулевой длительностью перехода больше не создаёт пустоты между строками в Safari.
|
|
12
|
+
|
|
13
|
+
Рост ответа не перезаписывает ещё не обработанный уход читателя вверх: положение учитывается до доводки низа, даже если браузер задержал событие scroll.
|
|
14
|
+
|
|
15
|
+
После открытия и немедленной отправки начальная прокрутка больше не удерживает асинхронную цель внизу: уход читателя вверх сохраняется при дальнейших замерах ответа. Обновление ничего не требует.
|
|
16
|
+
|
|
17
|
+
## 0.71.0
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- 8b8c651: Три вида поля Одуванчик: сжатое, обычное и расширенное. Настройки модели/провайдера/рассуждений из каталога, цена и метки, инструменты приложения, шторка телефона. Сфера и токены из опубликованных ds-react/ds-tokens. Необязательный договор скина v29, сохранение уровня ответа для подписи в истории.
|
|
22
|
+
|
|
3
23
|
## 0.70.1
|
|
4
24
|
|
|
5
25
|
No changes in this release.
|
|
@@ -367,6 +367,7 @@ var russianLabels = {
|
|
|
367
367
|
notices: russianNotices,
|
|
368
368
|
messengerStatus: russianMessengerStatus,
|
|
369
369
|
workView: russianWorkView,
|
|
370
|
+
composerSettings: { levels: { off: "\u0412\u044B\u043A\u043B", on: "\u0412\u043A\u043B", minimal: "\u041C\u0438\u043D\u0438\u043C\u0443\u043C", low: "\u041D\u0438\u0437\u043A\u043E", medium: "\u0421\u0440\u0435\u0434\u043D\u0435", high: "\u0412\u044B\u0441\u043E\u043A\u043E", max: "\u041C\u0430\u043A\u0441\u0438\u043C\u0443\u043C" }, model: "\u041C\u043E\u0434\u0435\u043B\u044C", reasoning: "\u0420\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043D\u0438\u044F", tools: "\u0418\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B", settings: "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u043E\u0442\u0432\u0435\u0442\u0430", done: "\u0413\u043E\u0442\u043E\u0432\u043E", via: "\u0427\u0435\u0440\u0435\u0437", search: "\u041D\u0430\u0439\u0442\u0438 \u043C\u043E\u0434\u0435\u043B\u044C", showReasoning: "\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0445\u043E\u0434 \u043C\u044B\u0441\u043B\u0438", project: "\u041F\u0440\u043E\u0435\u043A\u0442", file: "\u0424\u0430\u0439\u043B", image: "\u041A\u0430\u0440\u0442\u0438\u043D\u043A\u0430", textModels: "\u0422\u0435\u043A\u0441\u0442\u043E\u0432\u044B\u0435 \u0437\u0430\u0434\u0430\u0447\u0438", imageModels: "\u0422\u0435\u043A\u0441\u0442 \u0438 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F", models: "\u041C\u043E\u0434\u0435\u043B\u0438", noResults: "\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E", price: "USD \u0437\u0430 \u043C\u0438\u043B\u043B\u0438\u043E\u043D \u0442\u043E\u043A\u0435\u043D\u043E\u0432", input: "\u0432\u0445\u043E\u0434", output: "\u0432\u044B\u0445\u043E\u0434" },
|
|
370
371
|
composerPlaceholder: "\u041D\u0430\u043F\u0438\u0448\u0438\u0442\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435",
|
|
371
372
|
composerLabel: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435",
|
|
372
373
|
send: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C",
|
|
@@ -683,6 +684,7 @@ var englishLabels = {
|
|
|
683
684
|
locale: "en",
|
|
684
685
|
...englishWorkLabels,
|
|
685
686
|
workView: englishWorkViewLabels,
|
|
687
|
+
composerSettings: { levels: { off: "Off", on: "On", minimal: "Minimal", low: "Low", medium: "Medium", high: "High", max: "Max" }, model: "Model", reasoning: "Reasoning", tools: "Tools", settings: "Response settings", done: "Done", via: "Via", search: "Find model", showReasoning: "Show reasoning", project: "Project", file: "File", image: "Image", textModels: "Text tasks", imageModels: "Text and images", models: "Models", noResults: "No results", price: "USD per million tokens", input: "input", output: "output" },
|
|
686
688
|
composerPlaceholder: "Write a message",
|
|
687
689
|
composerLabel: "Message",
|
|
688
690
|
send: "Send",
|
|
@@ -961,6 +963,7 @@ function ChatLabelsProvider({ labels, children }) {
|
|
|
961
963
|
const resolved = useMemo(
|
|
962
964
|
() => ({
|
|
963
965
|
...labels,
|
|
966
|
+
composerSettings: { ...(labels.locale?.startsWith("en") ? englishLabels : russianLabels).composerSettings, ...labels.composerSettings },
|
|
964
967
|
externalImageLink: labels.externalImageLink ?? russianLabels.externalImageLink,
|
|
965
968
|
answerCutByLength: labels.answerCutByLength ?? russianLabels.answerCutByLength,
|
|
966
969
|
answerEdited: labels.answerEdited ?? russianLabels.answerEdited,
|
|
@@ -3886,6 +3889,10 @@ function useModelChoice({ api, chatId, savedChoice, savedChoicePending = false,
|
|
|
3886
3889
|
models: provider.models.map((model) => ({
|
|
3887
3890
|
id: model.id,
|
|
3888
3891
|
name: model.displayName,
|
|
3892
|
+
...model.group !== void 0 && { group: model.group },
|
|
3893
|
+
...model.description !== void 0 && { description: model.description },
|
|
3894
|
+
...model.tags !== void 0 && { tags: model.tags },
|
|
3895
|
+
...model.price !== void 0 && { price: model.price },
|
|
3889
3896
|
...typeof model.acceptsImages === "boolean" && { acceptsImages: model.acceptsImages }
|
|
3890
3897
|
}))
|
|
3891
3898
|
})),
|
|
@@ -4190,7 +4197,10 @@ var SCROLL_KEYS = /* @__PURE__ */ new Set([...JUMP_KEYS, "PageUp", "ArrowUp", "H
|
|
|
4190
4197
|
var READER_INPUT_WINDOW_MS = 250;
|
|
4191
4198
|
var UP_KEYS = /* @__PURE__ */ new Set(["PageUp", "ArrowUp", "Home"]);
|
|
4192
4199
|
function FeedItem({ style, children, ref }) {
|
|
4193
|
-
return /* @__PURE__ */ jsx3("div", { ref, style, "data-feed-item": "", children });
|
|
4200
|
+
return /* @__PURE__ */ jsx3("div", { ref, style: { ...style, transitionProperty: "none" }, "data-feed-item": "", children });
|
|
4201
|
+
}
|
|
4202
|
+
function FeedWindow({ style, children, ref }) {
|
|
4203
|
+
return /* @__PURE__ */ jsx3("div", { ref, style: { ...style, transitionProperty: "none" }, children });
|
|
4194
4204
|
}
|
|
4195
4205
|
function isTextField(target) {
|
|
4196
4206
|
if (!(target instanceof Element)) return false;
|
|
@@ -4207,6 +4217,7 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4207
4217
|
}, []);
|
|
4208
4218
|
const lastHeight = useRef7(0);
|
|
4209
4219
|
const lastTop = useRef7(0);
|
|
4220
|
+
const syncScrollState = useRef7(null);
|
|
4210
4221
|
const shrunkSinceScroll = useRef7(0);
|
|
4211
4222
|
const openedAtBottom = useRef7(false);
|
|
4212
4223
|
const userJumpUntil = useRef7(0);
|
|
@@ -4223,43 +4234,60 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4223
4234
|
const lastIndex = messages.length - 1;
|
|
4224
4235
|
useEffect6(() => setScrollerReady(true), []);
|
|
4225
4236
|
useLayoutEffect(() => {
|
|
4226
|
-
const
|
|
4237
|
+
const scroller2 = scrollRef.current;
|
|
4227
4238
|
const root = rootRef.current;
|
|
4228
|
-
if (!scrollerReady || !
|
|
4239
|
+
if (!scrollerReady || !scroller2 || !root) return;
|
|
4229
4240
|
const measure = () => {
|
|
4230
|
-
const offset = root.getBoundingClientRect().top -
|
|
4241
|
+
const offset = root.getBoundingClientRect().top - scroller2.getBoundingClientRect().top + scroller2.scrollTop;
|
|
4231
4242
|
setStartMargin(Math.max(0, Math.round(offset)));
|
|
4232
4243
|
};
|
|
4233
4244
|
measure();
|
|
4234
4245
|
const observer = new ResizeObserver(measure);
|
|
4235
|
-
observer.observe(
|
|
4246
|
+
observer.observe(scroller2);
|
|
4236
4247
|
return () => observer.disconnect();
|
|
4237
4248
|
}, [scrollRef, scrollerReady]);
|
|
4238
4249
|
useEffect6(() => {
|
|
4239
|
-
const
|
|
4240
|
-
if (!scrollerReady || !
|
|
4241
|
-
lastHeight.current =
|
|
4242
|
-
lastTop.current =
|
|
4250
|
+
const scroller2 = scrollRef.current;
|
|
4251
|
+
if (!scrollerReady || !scroller2) return;
|
|
4252
|
+
lastHeight.current = scroller2.scrollHeight;
|
|
4253
|
+
lastTop.current = scroller2.scrollTop;
|
|
4254
|
+
let anchor;
|
|
4255
|
+
const rememberAnchor = () => {
|
|
4256
|
+
const view = scroller2.getBoundingClientRect();
|
|
4257
|
+
for (const element of rootRef.current?.querySelectorAll("[data-feed-item]") ?? []) {
|
|
4258
|
+
if (element.style.visibility === "hidden") continue;
|
|
4259
|
+
const box = element.getBoundingClientRect();
|
|
4260
|
+
if (box.bottom > view.top && box.top < view.bottom) {
|
|
4261
|
+
anchor = { element, offset: box.top - view.top + scroller2.scrollTop };
|
|
4262
|
+
return;
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
anchor = void 0;
|
|
4266
|
+
};
|
|
4267
|
+
rememberAnchor();
|
|
4243
4268
|
const onScroll = () => {
|
|
4244
|
-
const height =
|
|
4245
|
-
const top =
|
|
4246
|
-
const near = Math.min(height, lastHeight.current) - top -
|
|
4269
|
+
const height = scroller2.scrollHeight;
|
|
4270
|
+
const top = scroller2.scrollTop;
|
|
4271
|
+
const near = Math.min(height, lastHeight.current) - top - scroller2.clientHeight < STICK_TO_BOTTOM_PX;
|
|
4247
4272
|
const shrunk = shrunkSinceScroll.current + Math.max(0, lastHeight.current - height);
|
|
4248
4273
|
shrunkSinceScroll.current = 0;
|
|
4249
4274
|
const step = top - lastTop.current;
|
|
4250
4275
|
const now = performance.now();
|
|
4251
4276
|
const readerActed = now < readerInputUntil.current || now < userJumpUntil.current;
|
|
4252
|
-
const
|
|
4277
|
+
const anchorShift = anchor && scroller2.contains(anchor.element) ? anchor.element.getBoundingClientRect().top - scroller2.getBoundingClientRect().top + top - anchor.offset : 0;
|
|
4278
|
+
const compensated = anchorShift < 0 && Math.abs(step - anchorShift) <= 1;
|
|
4279
|
+
const movedByLayout = step < 0 && (-step <= 2 * shrunk || compensated) && !readerActed;
|
|
4253
4280
|
lastTop.current = top;
|
|
4254
4281
|
lastHeight.current = height;
|
|
4282
|
+
rememberAnchor();
|
|
4255
4283
|
if (movedByLayout) {
|
|
4256
|
-
if (stuck.current)
|
|
4284
|
+
if (stuck.current) scroller2.scrollTop = height;
|
|
4257
4285
|
return;
|
|
4258
4286
|
}
|
|
4259
4287
|
if (step < 0) stick(readerActed ? false : near);
|
|
4260
4288
|
else if (step > 0) {
|
|
4261
4289
|
readerUpUntil.current = 0;
|
|
4262
|
-
if (near && (step <=
|
|
4290
|
+
if (near && (step <= scroller2.clientHeight || performance.now() < userJumpUntil.current)) stick(true);
|
|
4263
4291
|
}
|
|
4264
4292
|
};
|
|
4265
4293
|
const onKeyDown = (event) => {
|
|
@@ -4288,38 +4316,41 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4288
4316
|
const onPointerUp = () => {
|
|
4289
4317
|
if (userJumpUntil.current > performance.now() + POINTER_JUMP_WINDOW_MS) userJumpUntil.current = performance.now() + POINTER_JUMP_WINDOW_MS;
|
|
4290
4318
|
};
|
|
4291
|
-
|
|
4319
|
+
syncScrollState.current = onScroll;
|
|
4320
|
+
scroller2.addEventListener("scroll", onScroll, { passive: true });
|
|
4292
4321
|
document.addEventListener("keydown", onKeyDown);
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4322
|
+
scroller2.addEventListener("pointerdown", onPointerDown);
|
|
4323
|
+
scroller2.addEventListener("wheel", onWheel, { passive: true });
|
|
4324
|
+
scroller2.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
4325
|
+
scroller2.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
4297
4326
|
window.addEventListener("pointerup", onPointerUp);
|
|
4298
4327
|
window.addEventListener("pointercancel", onPointerUp);
|
|
4299
4328
|
return () => {
|
|
4300
|
-
|
|
4329
|
+
syncScrollState.current = null;
|
|
4330
|
+
scroller2.removeEventListener("scroll", onScroll);
|
|
4301
4331
|
document.removeEventListener("keydown", onKeyDown);
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4332
|
+
scroller2.removeEventListener("pointerdown", onPointerDown);
|
|
4333
|
+
scroller2.removeEventListener("wheel", onWheel);
|
|
4334
|
+
scroller2.removeEventListener("touchstart", onTouchStart);
|
|
4335
|
+
scroller2.removeEventListener("touchmove", onTouchMove);
|
|
4306
4336
|
window.removeEventListener("pointerup", onPointerUp);
|
|
4307
4337
|
window.removeEventListener("pointercancel", onPointerUp);
|
|
4308
4338
|
};
|
|
4309
4339
|
}, [scrollRef, scrollerReady, stick]);
|
|
4310
4340
|
useEffect6(() => {
|
|
4311
|
-
const
|
|
4341
|
+
const scroller2 = scrollRef.current;
|
|
4312
4342
|
const root = rootRef.current;
|
|
4313
|
-
if (!scrollerReady || !
|
|
4343
|
+
if (!scrollerReady || !scroller2 || !root) return;
|
|
4314
4344
|
const settleAtBottom = () => {
|
|
4315
|
-
|
|
4316
|
-
const
|
|
4345
|
+
if (scroller2.scrollTop < lastTop.current) syncScrollState.current?.();
|
|
4346
|
+
const height = scroller2.scrollHeight;
|
|
4347
|
+
const clientHeight = scroller2.clientHeight;
|
|
4317
4348
|
shrunkSinceScroll.current += Math.max(0, lastHeight.current - height);
|
|
4318
4349
|
lastHeight.current = height;
|
|
4319
4350
|
const needed = height > settledHeight.current || clientHeight < settledClientHeight.current;
|
|
4320
4351
|
settledHeight.current = height;
|
|
4321
4352
|
settledClientHeight.current = clientHeight;
|
|
4322
|
-
if (stuck.current && needed && performance.now() >= readerUpUntil.current)
|
|
4353
|
+
if (stuck.current && needed && performance.now() >= readerUpUntil.current) scroller2.scrollTop = height;
|
|
4323
4354
|
};
|
|
4324
4355
|
let followUp = 0;
|
|
4325
4356
|
const follow = () => {
|
|
@@ -4334,7 +4365,7 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4334
4365
|
const listObserver = new MutationObserver(follow);
|
|
4335
4366
|
listObserver.observe(root, { subtree: true, childList: true, attributes: true, attributeFilter: ["style"] });
|
|
4336
4367
|
const scrollerObserver = new ResizeObserver(follow);
|
|
4337
|
-
scrollerObserver.observe(
|
|
4368
|
+
scrollerObserver.observe(scroller2);
|
|
4338
4369
|
return () => {
|
|
4339
4370
|
listObserver.disconnect();
|
|
4340
4371
|
scrollerObserver.disconnect();
|
|
@@ -4349,8 +4380,8 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4349
4380
|
setPositioned(false);
|
|
4350
4381
|
return;
|
|
4351
4382
|
}
|
|
4352
|
-
const
|
|
4353
|
-
if (!scrollerReady || !
|
|
4383
|
+
const scroller2 = scrollRef.current;
|
|
4384
|
+
if (!scrollerReady || !scroller2 || openedAtBottom.current) return;
|
|
4354
4385
|
openedAtBottom.current = true;
|
|
4355
4386
|
const focusIndex = openAtMessageId === void 0 ? -1 : messages.findIndex((message) => message.id === openAtMessageId);
|
|
4356
4387
|
stick(focusIndex < 0 || focusIndex === lastIndex);
|
|
@@ -4358,12 +4389,14 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4358
4389
|
virtualizerRef.current?.scrollToIndex(focusIndex, { align: "start" });
|
|
4359
4390
|
openingScrollUntil.current = performance.now() + OPENING_SCROLL_QUIET_MS;
|
|
4360
4391
|
} else {
|
|
4361
|
-
|
|
4392
|
+
queueMicrotask(() => {
|
|
4393
|
+
if (rootRef.current?.isConnected && scrollRef.current === scroller2 && stuck.current) scroller2.scrollTop = scroller2.scrollHeight;
|
|
4394
|
+
});
|
|
4362
4395
|
openingScrollUntil.current = 0;
|
|
4363
4396
|
}
|
|
4364
4397
|
let frame = 0;
|
|
4365
4398
|
const cancel = () => {
|
|
4366
|
-
|
|
4399
|
+
scroller2.removeEventListener("scroll", settle);
|
|
4367
4400
|
cancelAnimationFrame(frame);
|
|
4368
4401
|
cancelSettle.current = null;
|
|
4369
4402
|
};
|
|
@@ -4372,7 +4405,7 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4372
4405
|
setPositioned(true);
|
|
4373
4406
|
};
|
|
4374
4407
|
cancelSettle.current = cancel;
|
|
4375
|
-
|
|
4408
|
+
scroller2.addEventListener("scroll", settle, { once: true });
|
|
4376
4409
|
frame = requestAnimationFrame(() => {
|
|
4377
4410
|
frame = requestAnimationFrame(settle);
|
|
4378
4411
|
});
|
|
@@ -4382,19 +4415,22 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4382
4415
|
stick(true);
|
|
4383
4416
|
if (performance.now() < openingScrollUntil.current) virtualizerRef.current?.scrollTo(BOTTOM_SCROLL_TARGET);
|
|
4384
4417
|
openingScrollUntil.current = 0;
|
|
4385
|
-
const
|
|
4386
|
-
if (
|
|
4418
|
+
const scroller2 = scrollRef.current;
|
|
4419
|
+
if (scroller2) scroller2.scrollTop = scroller2.scrollHeight;
|
|
4387
4420
|
}, [scrollRef, stick]);
|
|
4388
4421
|
useImperativeHandle(ref, () => ({ scrollToBottom }), [scrollToBottom]);
|
|
4389
4422
|
const virtualizer = virtualizerRef.current;
|
|
4390
4423
|
const editedIndex = keepMountedMessageId === void 0 ? -1 : messages.findIndex((message) => message.id === keepMountedMessageId);
|
|
4391
|
-
const
|
|
4424
|
+
const scroller = scrollRef.current;
|
|
4425
|
+
const keepBuffer = positioned && followingBottom && virtualizer && scroller && lastIndex >= 0;
|
|
4426
|
+
const bufferStart = keepBuffer ? Math.max(0, virtualizer.findItemIndex(scroller.scrollTop - BUFFER_PX)) : 0;
|
|
4427
|
+
const bufferEnd = keepBuffer ? Math.min(lastIndex, virtualizer.findItemIndex(scroller.scrollTop + scroller.clientHeight)) : -1;
|
|
4392
4428
|
const keepMounted = useMemo6(() => {
|
|
4393
|
-
const kept = new Set(Array.from({ length: Math.max(0,
|
|
4429
|
+
const kept = new Set(Array.from({ length: Math.max(0, bufferEnd - bufferStart + 1) }, (_, offset) => bufferStart + offset));
|
|
4394
4430
|
if (keepLastMounted && lastIndex >= 0) kept.add(lastIndex);
|
|
4395
4431
|
if (editedIndex >= 0) kept.add(editedIndex);
|
|
4396
4432
|
return [...kept].sort((a, b) => a - b);
|
|
4397
|
-
}, [editedIndex, keepLastMounted, lastIndex
|
|
4433
|
+
}, [bufferEnd, bufferStart, editedIndex, keepLastMounted, lastIndex]);
|
|
4398
4434
|
return /* @__PURE__ */ jsx3("div", { ref: rootRef, children: scrollerReady && /* @__PURE__ */ jsx3(
|
|
4399
4435
|
Virtualizer,
|
|
4400
4436
|
{
|
|
@@ -4404,6 +4440,7 @@ function MessageFeedView({ scrollRef, messages, renderMessage, keepLastMounted,
|
|
|
4404
4440
|
itemSize: UNMEASURED_MESSAGE_HEIGHT_PX,
|
|
4405
4441
|
bufferSize: positioned ? BUFFER_PX : 0,
|
|
4406
4442
|
item: FeedItem,
|
|
4443
|
+
as: FeedWindow,
|
|
4407
4444
|
keepMounted,
|
|
4408
4445
|
startMargin,
|
|
4409
4446
|
children: (message, index) => renderMessage(message, index)
|
|
@@ -5784,7 +5821,8 @@ function workLayoutOf(entries, { streaming, phrases, labels, thoughts = false })
|
|
|
5784
5821
|
}
|
|
5785
5822
|
if (streaming && lastStep > lastShown) {
|
|
5786
5823
|
const live = liveStepOf(group, phrases, labels);
|
|
5787
|
-
|
|
5824
|
+
const completed = doneLinesOf((thoughts ? group : group.filter((step) => step.kind === "tool")).filter((step) => step.kind === "tool" && step.call.state !== "running"), phrases, labels, false).items;
|
|
5825
|
+
layout.push({ kind: "live", key, phrase: labels.live(live.phrase), icon: live.icon, ...completed.length > 0 && { completed } });
|
|
5788
5826
|
} else {
|
|
5789
5827
|
const done = doneLinesOf(thoughts ? group : group.filter((step) => step.kind === "tool"), phrases, labels, !streaming);
|
|
5790
5828
|
if (done.count > 0) layout.push({ kind: "done", key, ...done });
|
|
@@ -5846,7 +5884,7 @@ function WorkStepsPart({
|
|
|
5846
5884
|
const labels = useChatLabels();
|
|
5847
5885
|
const [open, setOpen] = usePartOpen(expanded, `${item.key}:work`);
|
|
5848
5886
|
if (skin.WorkSteps) {
|
|
5849
|
-
return item.kind === "live" ? /* @__PURE__ */ jsx8(skin.WorkSteps, { state: "live", phrase: item.phrase, icon: item.icon }) : /* @__PURE__ */ jsx8(
|
|
5887
|
+
return item.kind === "live" ? /* @__PURE__ */ jsx8(skin.WorkSteps, { state: "live", phrase: item.phrase, icon: item.icon, ...item.completed && { completed: item.completed } }) : /* @__PURE__ */ jsx8(
|
|
5850
5888
|
skin.WorkSteps,
|
|
5851
5889
|
{
|
|
5852
5890
|
state: "done",
|
|
@@ -5881,7 +5919,7 @@ function SubjectAgentChat(props) {
|
|
|
5881
5919
|
if (found.state === "failed") return /* @__PURE__ */ jsx9(props.skin.ErrorNotice, { kind: "other", onRetry: found.retry });
|
|
5882
5920
|
return /* @__PURE__ */ jsx9(SubjectChatLoading, { skin: props.skin });
|
|
5883
5921
|
}
|
|
5884
|
-
function AgentChatBody({ api, chatId, skin, liveness, voice, voiceDialog, attachments: attachmentsPlugin, spendingLimits, onBusyChange, appBridge, initialDraft, answerEditing, onFeedChange, messageActions, onTurnFinished, onTurnRefused, composerActions, onAppEvent, onChatAccessChange, onStateChange, onModelChosen, onChatUnavailable, reloadKey, steering, widgets, diagrams, liveDemos, images, videos, appEvents, workView, stepPhrases, noticeLines }) {
|
|
5922
|
+
function AgentChatBody({ composerOptions, api, chatId, skin, liveness, voice, voiceDialog, attachments: attachmentsPlugin, spendingLimits, onBusyChange, appBridge, initialDraft, answerEditing, onFeedChange, messageActions, onTurnFinished, onTurnRefused, composerActions, onAppEvent, onChatAccessChange, onStateChange, onModelChosen, onChatUnavailable, reloadKey, steering, widgets, diagrams, liveDemos, images, videos, appEvents, workView, stepPhrases, noticeLines, answerDetails }) {
|
|
5885
5923
|
const spendingNoticeId = useId2();
|
|
5886
5924
|
const closedNoticeId = useId2();
|
|
5887
5925
|
const chat = useAgentChat({
|
|
@@ -5913,8 +5951,17 @@ function AgentChatBody({ api, chatId, skin, liveness, voice, voiceDialog, attach
|
|
|
5913
5951
|
const attachments = attachmentsPlugin?.useController({ api, chatId, modelSeesImages: chatModelSeesImages });
|
|
5914
5952
|
const describeFiles = attachments?.describe;
|
|
5915
5953
|
const imageClients = useSameList(imageClientsOf(images));
|
|
5954
|
+
const [localReasoningVisible, setLocalReasoningVisible] = useState18(true);
|
|
5955
|
+
const showReasoning = composerOptions?.reasoningVisibility?.value ?? localReasoningVisible;
|
|
5956
|
+
const effectiveComposerOptions = useMemo16(() => ({ ...composerOptions, reasoningVisibility: composerOptions?.reasoningVisibility ?? { value: showReasoning, onChange: setLocalReasoningVisible } }), [composerOptions, showReasoning]);
|
|
5957
|
+
const showAnswerDetails = answerDetails ?? composerOptions?.variant === "extended";
|
|
5958
|
+
const answerNamesKey = showAnswerDetails ? JSON.stringify(modelChoice.providers.map(({ id, name, models }) => ({ id, name, models: models.map(({ id: id2, name: name2 }) => ({ id: id2, name: name2 })) }))) : "";
|
|
5959
|
+
const answerModelNames = useMemo16(() => answerNamesKey ? JSON.parse(answerNamesKey) : void 0, [answerNamesKey]);
|
|
5916
5960
|
const extensions = useMemo16(
|
|
5917
5961
|
() => ({
|
|
5962
|
+
reasoningVisible: showReasoning,
|
|
5963
|
+
answerDetails: showAnswerDetails,
|
|
5964
|
+
...answerModelNames && { modelNames: answerModelNames },
|
|
5918
5965
|
...widgets && { widgets },
|
|
5919
5966
|
...diagrams && { diagrams },
|
|
5920
5967
|
...liveDemos && { liveDemos },
|
|
@@ -5925,7 +5972,7 @@ function AgentChatBody({ api, chatId, skin, liveness, voice, voiceDialog, attach
|
|
|
5925
5972
|
...stepPhrases && { stepPhrases },
|
|
5926
5973
|
...noticeLines && { noticeLines }
|
|
5927
5974
|
}),
|
|
5928
|
-
[widgets, diagrams, liveDemos, imageClients, videos, appEvents, workView, stepPhrases, noticeLines]
|
|
5975
|
+
[widgets, diagrams, liveDemos, imageClients, videos, appEvents, workView, stepPhrases, noticeLines, showReasoning, showAnswerDetails, answerModelNames]
|
|
5929
5976
|
);
|
|
5930
5977
|
const scrollRef = useRef17(null);
|
|
5931
5978
|
const feedRef = useRef17(null);
|
|
@@ -6301,6 +6348,7 @@ ${text}` : text),
|
|
|
6301
6348
|
composer: /* @__PURE__ */ jsx9(
|
|
6302
6349
|
skin.Composer,
|
|
6303
6350
|
{
|
|
6351
|
+
options: effectiveComposerOptions,
|
|
6304
6352
|
value: chat.value,
|
|
6305
6353
|
onValueChange: chat.setValue,
|
|
6306
6354
|
onSubmit: submitComposer,
|
|
@@ -6496,6 +6544,7 @@ var AgentAnswer = memo4(function AgentAnswer2({
|
|
|
6496
6544
|
const imagesView = isToolUIPart3(part) ? describeImages?.(part) : void 0;
|
|
6497
6545
|
const videoView = isToolUIPart3(part) && extensions.videos && getToolName5(part) === extensions.videos.toolName ? extensions.videos.describe(part) : void 0;
|
|
6498
6546
|
if (part.type === "reasoning") {
|
|
6547
|
+
if (extensions.reasoningVisible === false) return;
|
|
6499
6548
|
const ordinal = String(reasoningIndex++);
|
|
6500
6549
|
const streaming = part.state === "streaming";
|
|
6501
6550
|
const durationMs = streaming ? null : durations[ordinal] ?? null;
|
|
@@ -6631,9 +6680,12 @@ var AgentAnswer = memo4(function AgentAnswer2({
|
|
|
6631
6680
|
}));
|
|
6632
6681
|
const errorText = status === "error" ? customErrorText(labels, message.metadata?.error) : void 0;
|
|
6633
6682
|
const notice = status === "error" ? /* @__PURE__ */ jsx9(skin.ErrorNotice, { kind: message.metadata?.error?.kind ?? "other", ...errorText !== void 0 && { text: errorText }, ...onRetry && { onRetry } }) : void 0;
|
|
6683
|
+
const answerProvider = extensions.modelNames?.find((provider) => provider.id === message.metadata?.providerId);
|
|
6684
|
+
const answerModel = answerProvider?.models.find((model) => model.id === message.metadata?.modelId);
|
|
6634
6685
|
return /* @__PURE__ */ jsx9(ThinkingClockProvider, { id: message.id, waiting: status === "streaming", children: /* @__PURE__ */ jsxs(
|
|
6635
6686
|
skin.AgentMessage,
|
|
6636
6687
|
{
|
|
6688
|
+
...extensions.answerDetails && message.metadata?.modelId && message.metadata?.providerId && { modelDetails: { modelId: message.metadata.modelId, providerId: message.metadata.providerId, ...answerProvider && { providerName: answerProvider.name }, ...answerModel && { modelName: answerModel.name }, ...message.metadata.reasoningLevel !== void 0 && { reasoning: message.metadata.reasoningLevel } } },
|
|
6637
6689
|
status,
|
|
6638
6690
|
empty: !steered && status !== "streaming" && status !== "awaiting_approval" && text.trim().length === 0,
|
|
6639
6691
|
onCopy: () => void navigator.clipboard?.writeText(text),
|
|
@@ -7172,4 +7224,4 @@ export {
|
|
|
7172
7224
|
activeChatTitle,
|
|
7173
7225
|
useWorkspaceListSync
|
|
7174
7226
|
};
|
|
7175
|
-
//# sourceMappingURL=chunk-
|
|
7227
|
+
//# sourceMappingURL=chunk-WJJY2WLQ.js.map
|