quassel 0.2.1 → 0.3.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/ChatActionDock.d.ts +2 -0
- package/ChatMessages.d.ts +5 -1
- package/QuasselProvider.d.ts +10 -2
- package/README.md +10 -4
- package/chat.css +56 -35
- package/elapsed.d.ts +16 -0
- package/index.d.ts +2 -1
- package/index.js +185 -59
- package/index.js.map +4 -4
- package/package.json +1 -1
- package/texts.d.ts +1 -1
- package/ui/popover.d.ts +3 -1
package/index.js
CHANGED
|
@@ -24,6 +24,7 @@ var defaultTexts = {
|
|
|
24
24
|
working: "Arbeitet ...",
|
|
25
25
|
toolRunning: "l\xE4uft ...",
|
|
26
26
|
toolStillRunning: "Werkzeug l\xE4uft ...",
|
|
27
|
+
toolElapsedSeconds: "{seconds} s",
|
|
27
28
|
currentTool: "Werkzeug l\xE4uft",
|
|
28
29
|
thinkingChip: "Denken",
|
|
29
30
|
toolChip: "Werkzeug",
|
|
@@ -42,7 +43,6 @@ var defaultTexts = {
|
|
|
42
43
|
placeholder: "Nachricht schreiben ...",
|
|
43
44
|
steeringPlaceholder: "Dazwischenfunken ...",
|
|
44
45
|
steered: "In den laufenden Turn eingespeist",
|
|
45
|
-
inputHint: "Enter zum Senden - Shift + Enter f\xFCr eine neue Zeile",
|
|
46
46
|
detailModeTitle: "Detailgrad der Schritte",
|
|
47
47
|
detailModeOff: "nur Antworten",
|
|
48
48
|
detailModeCurrent: "aktuell",
|
|
@@ -87,10 +87,11 @@ var defaultTexts = {
|
|
|
87
87
|
|
|
88
88
|
// packages/quassel/src/ui/cn.ts
|
|
89
89
|
import { createCn } from "cn/config";
|
|
90
|
-
var cn = createCn({ prefix: "qsl" });
|
|
90
|
+
var cn = createCn({ prefix: "qsl", extend: { theme: { text: ["meta", "trace", "label"] } } });
|
|
91
91
|
|
|
92
92
|
// packages/quassel/src/ChatMessages.tsx
|
|
93
93
|
import { useCallback as useCallback2, useContext as useContext3, useEffect as useEffect3, useLayoutEffect, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
94
|
+
import { createPortal } from "react-dom";
|
|
94
95
|
|
|
95
96
|
// packages/quassel/src/chat-scroll.ts
|
|
96
97
|
var atEnd = (viewport) => viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop <= 24;
|
|
@@ -154,12 +155,12 @@ var buttonVariants = cva(
|
|
|
154
155
|
},
|
|
155
156
|
size: {
|
|
156
157
|
default: "qsl:h-8 qsl:gap-1.5 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2",
|
|
157
|
-
xs: "qsl:h-6 qsl:gap-1 qsl:rounded-[min(
|
|
158
|
-
sm: "qsl:h-7 qsl:gap-1 qsl:rounded-[min(
|
|
158
|
+
xs: "qsl:h-6 qsl:gap-1 qsl:rounded-[min(--theme(--radius-md),10px)] qsl:px-2 qsl:text-xs qsl:in-data-[slot=button-group]:rounded-lg qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3",
|
|
159
|
+
sm: "qsl:h-7 qsl:gap-1 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:px-2.5 qsl:text-[0.8rem] qsl:in-data-[slot=button-group]:rounded-lg qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3.5",
|
|
159
160
|
lg: "qsl:h-9 qsl:gap-1.5 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2",
|
|
160
161
|
icon: "qsl:size-8",
|
|
161
|
-
"icon-xs": "qsl:size-6 qsl:rounded-[min(
|
|
162
|
-
"icon-sm": "qsl:size-7 qsl:rounded-[min(
|
|
162
|
+
"icon-xs": "qsl:size-6 qsl:rounded-[min(--theme(--radius-md),10px)] qsl:in-data-[slot=button-group]:rounded-lg qsl:[&_svg:not([class*='size-'])]:size-3",
|
|
163
|
+
"icon-sm": "qsl:size-7 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:in-data-[slot=button-group]:rounded-lg",
|
|
163
164
|
"icon-lg": "qsl:size-9"
|
|
164
165
|
}
|
|
165
166
|
},
|
|
@@ -223,9 +224,10 @@ function PopoverContent({
|
|
|
223
224
|
anchor,
|
|
224
225
|
collisionPadding,
|
|
225
226
|
keepMounted,
|
|
227
|
+
portalContainer,
|
|
226
228
|
...props
|
|
227
229
|
}) {
|
|
228
|
-
return /* @__PURE__ */ jsx3(PopoverPrimitive.Portal, { keepMounted, children: /* @__PURE__ */ jsx3(
|
|
230
|
+
return /* @__PURE__ */ jsx3(PopoverPrimitive.Portal, { container: portalContainer, keepMounted, children: /* @__PURE__ */ jsx3(
|
|
229
231
|
PopoverPrimitive.Positioner,
|
|
230
232
|
{
|
|
231
233
|
align,
|
|
@@ -239,6 +241,7 @@ function PopoverContent({
|
|
|
239
241
|
PopoverPrimitive.Popup,
|
|
240
242
|
{
|
|
241
243
|
"data-quassel": "",
|
|
244
|
+
"data-quassel-popover": "",
|
|
242
245
|
"data-slot": "popover-content",
|
|
243
246
|
className: cn(
|
|
244
247
|
"qsl:z-[110] qsl:flex qsl:w-72 qsl:origin-(--transform-origin) qsl:flex-col qsl:gap-2.5 qsl:rounded-lg qsl:bg-popover qsl:p-2.5 qsl:text-sm qsl:text-popover-foreground qsl:shadow-md qsl:ring-1 qsl:ring-foreground/10 qsl:outline-hidden qsl:duration-100 qsl:data-[side=bottom]:slide-in-from-top-2 qsl:data-[side=inline-end]:slide-in-from-left-2 qsl:data-[side=inline-start]:slide-in-from-right-2 qsl:data-[side=left]:slide-in-from-right-2 qsl:data-[side=right]:slide-in-from-left-2 qsl:data-[side=top]:slide-in-from-bottom-2 qsl:data-open:animate-in qsl:data-open:fade-in-0 qsl:data-open:zoom-in-95 qsl:data-closed:animate-out qsl:data-closed:fade-out-0 qsl:data-closed:zoom-out-95",
|
|
@@ -285,7 +288,7 @@ var toggleVariants = cva2(
|
|
|
285
288
|
},
|
|
286
289
|
size: {
|
|
287
290
|
default: "qsl:h-8 qsl:min-w-8 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2",
|
|
288
|
-
sm: "qsl:h-7 qsl:min-w-7 qsl:rounded-[min(
|
|
291
|
+
sm: "qsl:h-7 qsl:min-w-7 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:px-2.5 qsl:text-[0.8rem] qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3.5",
|
|
289
292
|
lg: "qsl:h-9 qsl:min-w-9 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2"
|
|
290
293
|
}
|
|
291
294
|
},
|
|
@@ -316,16 +319,22 @@ function Toggle({
|
|
|
316
319
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
317
320
|
var defaultComponents = { Button, Toggle, Card, StopButton, Popover, PopoverContent };
|
|
318
321
|
var QuasselContext = createContext({ components: defaultComponents });
|
|
319
|
-
function QuasselProvider({ components: components2, allowUrl, children }) {
|
|
322
|
+
function QuasselProvider({ components: components2, allowUrl, portalContainer, children }) {
|
|
320
323
|
const outer = useContext(QuasselContext);
|
|
321
324
|
const value = useMemo(() => ({
|
|
322
325
|
components: { ...outer.components, ...components2 },
|
|
323
|
-
allowUrl: allowUrl ?? outer.allowUrl
|
|
324
|
-
|
|
326
|
+
allowUrl: allowUrl ?? outer.allowUrl,
|
|
327
|
+
portalContainer: portalContainer ?? outer.portalContainer
|
|
328
|
+
}), [outer, components2, allowUrl, portalContainer]);
|
|
325
329
|
return /* @__PURE__ */ jsx7(QuasselContext.Provider, { value, children });
|
|
326
330
|
}
|
|
327
331
|
var useQuasselComponents = () => useContext(QuasselContext).components;
|
|
328
332
|
var useAllowUrl = () => useContext(QuasselContext).allowUrl;
|
|
333
|
+
function useQuasselPortalContainer() {
|
|
334
|
+
const container = useContext(QuasselContext).portalContainer;
|
|
335
|
+
const target = typeof container === "function" ? container() : container && "current" in container ? container.current : container;
|
|
336
|
+
return target ?? void 0;
|
|
337
|
+
}
|
|
329
338
|
|
|
330
339
|
// packages/quassel/src/useChatAction.ts
|
|
331
340
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -506,7 +515,7 @@ function isTableDivider(line) {
|
|
|
506
515
|
import { useMemo as useMemo2 } from "react";
|
|
507
516
|
import { SparklesIcon, WrenchIcon, XIcon } from "lucide-react";
|
|
508
517
|
import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
509
|
-
var preClasses = "qsl:rounded-lg qsl:bg-secondary qsl:p-3 qsl:font-mono qsl:text-
|
|
518
|
+
var preClasses = "qsl:rounded-lg qsl:bg-secondary qsl:p-3 qsl:font-mono qsl:text-trace qsl:leading-[1.625] qsl:break-all qsl:whitespace-pre-wrap";
|
|
510
519
|
function StepPopover({
|
|
511
520
|
message,
|
|
512
521
|
position,
|
|
@@ -519,6 +528,7 @@ function StepPopover({
|
|
|
519
528
|
contextElement: document.documentElement
|
|
520
529
|
}), [position]);
|
|
521
530
|
const { Button: Button2, Popover: Popover2, PopoverContent: PopoverContent2 } = useQuasselComponents();
|
|
531
|
+
const portalContainer = useQuasselPortalContainer();
|
|
522
532
|
const tool = message.tool;
|
|
523
533
|
const thinking = message.role === "thinking";
|
|
524
534
|
const title = thinking ? texts.thinkingTitle : texts.toolTitle;
|
|
@@ -535,6 +545,7 @@ function StepPopover({
|
|
|
535
545
|
thinking ? "qsl:max-h-none" : "qsl:max-h-[min(70vh,620px)]"
|
|
536
546
|
),
|
|
537
547
|
collisionPadding: 16,
|
|
548
|
+
portalContainer,
|
|
538
549
|
side: "bottom",
|
|
539
550
|
sideOffset: 10,
|
|
540
551
|
children: [
|
|
@@ -554,13 +565,13 @@ function StepPopover({
|
|
|
554
565
|
}
|
|
555
566
|
function PopoverSection({ label, value, error = false }) {
|
|
556
567
|
return /* @__PURE__ */ jsxs2("section", { children: [
|
|
557
|
-
/* @__PURE__ */ jsx9("h3", { className: "qsl:mb-1.5 qsl:text-
|
|
568
|
+
/* @__PURE__ */ jsx9("h3", { className: "qsl:mb-1.5 qsl:text-trace qsl:font-semibold qsl:tracking-[0.04em] qsl:text-muted-foreground qsl:uppercase", children: label }),
|
|
558
569
|
/* @__PURE__ */ jsx9("pre", { className: cn(preClasses, error && "qsl:text-destructive"), children: value })
|
|
559
570
|
] });
|
|
560
571
|
}
|
|
561
572
|
|
|
562
573
|
// packages/quassel/src/PendingActionCard.tsx
|
|
563
|
-
import { CheckIcon as CheckIcon2 } from "lucide-react";
|
|
574
|
+
import { CheckIcon as CheckIcon2, XIcon as XIcon2 } from "lucide-react";
|
|
564
575
|
import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
565
576
|
var cardClasses = "qsl:gap-2.5 qsl:bg-background qsl:px-3.5 qsl:text-sm";
|
|
566
577
|
var resultText = (result) => typeof result === "string" ? result : result === null || result === void 0 ? "" : JSON.stringify(result);
|
|
@@ -577,7 +588,7 @@ function PendingActionCard({
|
|
|
577
588
|
return /* @__PURE__ */ jsxs3(Card2, { className: cardClasses, size: "sm", children: [
|
|
578
589
|
/* @__PURE__ */ jsx10("div", { className: "qsl:leading-normal", children: text }),
|
|
579
590
|
/* @__PURE__ */ jsxs3("div", { className: "qsl:flex qsl:items-center qsl:gap-1.5 qsl:text-sm qsl:text-muted-foreground", "data-action": "resolved", children: [
|
|
580
|
-
/* @__PURE__ */ jsx10(CheckIcon2, { className: "qsl:text-success", size: 12 }),
|
|
591
|
+
action.status === "approved" ? /* @__PURE__ */ jsx10(CheckIcon2, { className: "qsl:text-success", size: 12 }) : /* @__PURE__ */ jsx10(XIcon2, { size: 12 }),
|
|
581
592
|
action.status === "approved" ? resultText(action.result) : dismissedLabel
|
|
582
593
|
] })
|
|
583
594
|
] });
|
|
@@ -878,6 +889,53 @@ function timestampDay(date, options = {}) {
|
|
|
878
889
|
return { key, label };
|
|
879
890
|
}
|
|
880
891
|
|
|
892
|
+
// packages/quassel/src/elapsed.ts
|
|
893
|
+
import { useSyncExternalStore } from "react";
|
|
894
|
+
var tickMs = 500;
|
|
895
|
+
function formatElapsed(ms, texts) {
|
|
896
|
+
const total = Math.max(0, Math.floor(ms / 1e3));
|
|
897
|
+
if (total < 60) return fillText(texts.toolElapsedSeconds, { seconds: total });
|
|
898
|
+
const hours = Math.floor(total / 3600);
|
|
899
|
+
const minutes = Math.floor(total / 60) % 60;
|
|
900
|
+
const seconds = String(total % 60).padStart(2, "0");
|
|
901
|
+
return hours > 0 ? `${hours}:${String(minutes).padStart(2, "0")}:${seconds}` : `${minutes}:${seconds}`;
|
|
902
|
+
}
|
|
903
|
+
function createTicker(intervalMs = tickMs) {
|
|
904
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
905
|
+
let now = Date.now();
|
|
906
|
+
let timer;
|
|
907
|
+
return {
|
|
908
|
+
subscribe(listener) {
|
|
909
|
+
listeners.add(listener);
|
|
910
|
+
if (timer === void 0) {
|
|
911
|
+
now = Date.now();
|
|
912
|
+
timer = setInterval(() => {
|
|
913
|
+
now = Date.now();
|
|
914
|
+
listeners.forEach((notify) => notify());
|
|
915
|
+
}, intervalMs);
|
|
916
|
+
}
|
|
917
|
+
return () => {
|
|
918
|
+
listeners.delete(listener);
|
|
919
|
+
if (listeners.size === 0 && timer !== void 0) {
|
|
920
|
+
clearInterval(timer);
|
|
921
|
+
timer = void 0;
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
},
|
|
925
|
+
now() {
|
|
926
|
+
const current = Date.now();
|
|
927
|
+
if (timer === void 0 && (current - now >= intervalMs || current < now)) now = current;
|
|
928
|
+
return now;
|
|
929
|
+
},
|
|
930
|
+
active: () => timer !== void 0
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
var elapsedTicker = createTicker();
|
|
934
|
+
var nothingOnServer = () => void 0;
|
|
935
|
+
function useElapsed(start) {
|
|
936
|
+
return useSyncExternalStore(elapsedTicker.subscribe, () => Math.floor((elapsedTicker.now() - start) / 1e3) * 1e3, nothingOnServer);
|
|
937
|
+
}
|
|
938
|
+
|
|
881
939
|
// packages/quassel/src/MessageActions.tsx
|
|
882
940
|
import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon2, PencilIcon, RotateCcwIcon } from "lucide-react";
|
|
883
941
|
import { useState as useState3 } from "react";
|
|
@@ -943,6 +1001,10 @@ function createChatSendScope(enabled) {
|
|
|
943
1001
|
};
|
|
944
1002
|
}
|
|
945
1003
|
|
|
1004
|
+
// packages/quassel/src/ChatActionDock.ts
|
|
1005
|
+
import { createContext as createContext4 } from "react";
|
|
1006
|
+
var ChatActionDock = createContext4(void 0);
|
|
1007
|
+
|
|
946
1008
|
// packages/quassel/src/announce.ts
|
|
947
1009
|
var abstandMs = 400;
|
|
948
1010
|
var hoechstensWartend = 5;
|
|
@@ -1005,7 +1067,7 @@ function announce(text) {
|
|
|
1005
1067
|
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1006
1068
|
var stepClasses = "qsl:mt-[var(--qsl-chat-message-gap,16px)]";
|
|
1007
1069
|
var denseStepClasses = "qsl:mt-[var(--qsl-chat-dense-message-gap,8px)]";
|
|
1008
|
-
var traceClasses = "qsl:flex qsl:w-full qsl:gap-2 qsl:pl-6 qsl:text-left qsl:text-
|
|
1070
|
+
var traceClasses = "qsl:flex qsl:w-full qsl:gap-2 qsl:pl-6 qsl:text-left qsl:text-trace qsl:leading-[1.375] qsl:text-muted-foreground";
|
|
1009
1071
|
var traceButtonClasses = "qsl:cursor-pointer qsl:rounded-md qsl:py-1 qsl:pr-2 qsl:transition-colors qsl:hover:bg-secondary qsl:hover:text-foreground qsl:focus-visible:bg-secondary qsl:focus-visible:text-foreground qsl:focus-visible:outline-none";
|
|
1010
1072
|
var traceIconClasses = "qsl:mt-0.5 qsl:flex-none qsl:opacity-60";
|
|
1011
1073
|
var traceErrorIconClasses = "qsl:mt-0.5 qsl:flex-none qsl:text-destructive qsl:opacity-100";
|
|
@@ -1013,7 +1075,7 @@ var traceLineClasses = "qsl:min-w-0 qsl:self-baseline qsl:font-mono qsl:[overflo
|
|
|
1013
1075
|
var traceRunningClasses = "qsl:ml-1.5 qsl:opacity-60";
|
|
1014
1076
|
var chipClasses = cn(
|
|
1015
1077
|
"qsl:inline-flex qsl:max-w-[220px] qsl:items-center qsl:gap-[5px] qsl:rounded-full qsl:border qsl:border-border-soft qsl:px-2.5 qsl:py-0.5",
|
|
1016
|
-
"qsl:font-mono qsl:text-
|
|
1078
|
+
"qsl:font-mono qsl:text-meta qsl:leading-[1.6] qsl:text-muted-foreground qsl:transition-colors",
|
|
1017
1079
|
"qsl:data-[state=running]:border-[color-mix(in_srgb,var(--qsl-primary)_40%,var(--qsl-border-soft))]",
|
|
1018
1080
|
"qsl:data-[state=thinking]:border-[color-mix(in_srgb,var(--qsl-primary)_40%,var(--qsl-border-soft))]",
|
|
1019
1081
|
"qsl:data-[state=error]:border-[color-mix(in_srgb,var(--qsl-destructive)_45%,var(--qsl-border-soft))]",
|
|
@@ -1026,6 +1088,9 @@ var bubbleBodyClasses = "qsl:relative qsl:max-w-[86%] qsl:px-3 qsl:py-2 qsl:lead
|
|
|
1026
1088
|
function istSchritt(message) {
|
|
1027
1089
|
return !!message && (message.role === "thinking" || message.role === "tool");
|
|
1028
1090
|
}
|
|
1091
|
+
function istOffeneAktion(message) {
|
|
1092
|
+
return message.role === "action" && message.action !== void 0 && message.action.status === void 0;
|
|
1093
|
+
}
|
|
1029
1094
|
function defaultArgumentsText(tool) {
|
|
1030
1095
|
return prettyJson(tool.arguments);
|
|
1031
1096
|
}
|
|
@@ -1044,6 +1109,7 @@ function ChatMessages({
|
|
|
1044
1109
|
onLinkClick,
|
|
1045
1110
|
emptyState,
|
|
1046
1111
|
className,
|
|
1112
|
+
scrollerClassName,
|
|
1047
1113
|
showTimestamps = false,
|
|
1048
1114
|
announce: announce2,
|
|
1049
1115
|
scrollerRef,
|
|
@@ -1054,7 +1120,8 @@ function ChatMessages({
|
|
|
1054
1120
|
timestampOptions,
|
|
1055
1121
|
codeBlockOptions,
|
|
1056
1122
|
bubbleOptions,
|
|
1057
|
-
messageActions
|
|
1123
|
+
messageActions,
|
|
1124
|
+
toolElapsedThreshold = 3e3
|
|
1058
1125
|
}) {
|
|
1059
1126
|
const alleTexte = { ...defaultTexts, ...texts };
|
|
1060
1127
|
const { Button: Button2 } = useQuasselComponents();
|
|
@@ -1065,6 +1132,7 @@ function ChatMessages({
|
|
|
1065
1132
|
const [showJumpToEnd, setShowJumpToEnd] = useState4(false);
|
|
1066
1133
|
const [scroll] = useState4(() => createChatScroll());
|
|
1067
1134
|
const sendScope = useContext3(ChatSendContext);
|
|
1135
|
+
const dock = useContext3(ChatActionDock);
|
|
1068
1136
|
const [now, setNow] = useState4(() => Date.now());
|
|
1069
1137
|
useEffect3(() => {
|
|
1070
1138
|
if (!showTimestamps || timestampOptions?.format !== "relative") return;
|
|
@@ -1074,7 +1142,7 @@ function ChatMessages({
|
|
|
1074
1142
|
}, [showTimestamps, timestampOptions?.format]);
|
|
1075
1143
|
const angesagt = useRef3(new Set(messages.map((message) => message.key)));
|
|
1076
1144
|
useEffect3(() => {
|
|
1077
|
-
const faellig = messages.filter((message, index) => !angesagt.current.has(message.key) && (message.role === "action" ? message
|
|
1145
|
+
const faellig = messages.filter((message, index) => !angesagt.current.has(message.key) && (message.role === "action" ? istOffeneAktion(message) : message.role === "assistant" && message.text.trim() !== "" && (message.closed === true || !running && index === messages.length - 1)));
|
|
1078
1146
|
if (faellig.length === 0) {
|
|
1079
1147
|
return;
|
|
1080
1148
|
}
|
|
@@ -1137,6 +1205,9 @@ function ChatMessages({
|
|
|
1137
1205
|
() => {
|
|
1138
1206
|
const letzterFremder = messages.reduce((last, message, index) => message.role === "user" ? last : index, -1);
|
|
1139
1207
|
return messages.filter((message, index) => {
|
|
1208
|
+
if (dock !== void 0 && istOffeneAktion(message)) {
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1140
1211
|
if (detailMode === "current" && istSchritt(message)) {
|
|
1141
1212
|
return running && index === letzterFremder && (message.role === "thinking" ? !message.closed : stepState(message) === "running");
|
|
1142
1213
|
}
|
|
@@ -1149,29 +1220,32 @@ function ChatMessages({
|
|
|
1149
1220
|
return true;
|
|
1150
1221
|
});
|
|
1151
1222
|
},
|
|
1152
|
-
[messages, detailMode, running]
|
|
1223
|
+
[messages, detailMode, running, dock]
|
|
1153
1224
|
);
|
|
1225
|
+
const offeneAktionen = dock ? messages.filter(istOffeneAktion) : [];
|
|
1154
1226
|
const mitZeit = (inhalt, key, at, dicht = false) => showTimestamps ? /* @__PURE__ */ jsxs6("div", { className: cn("qsl:flex qsl:items-baseline qsl:gap-2", dicht ? denseStepClasses : stepClasses), children: [
|
|
1155
1227
|
/* @__PURE__ */ jsx13("time", { dateTime: messageDate(at)?.toISOString(), className: cn(
|
|
1156
|
-
"qsl:flex-none qsl:text-
|
|
1228
|
+
"qsl:flex-none qsl:text-meta qsl:tabular-nums qsl:text-muted-foreground qsl:opacity-85",
|
|
1157
1229
|
timestampOptions?.format && timestampOptions.format !== "time" ? "qsl:w-[clamp(60px,20%,120px)]" : "qsl:w-[34px]"
|
|
1158
1230
|
), children: messageDate(at) ? timestampLabel(messageDate(at), timestampOptions, now) : "" }),
|
|
1159
1231
|
/* @__PURE__ */ jsx13("div", { className: "qsl:min-w-0 qsl:flex-1 qsl:[&>*:first-child]:mt-0", children: inhalt })
|
|
1160
1232
|
] }, `zeit-${key}`) : inhalt;
|
|
1161
1233
|
const chipModus = detailMode === "current" || detailMode === "chips" || detailMode === "icons";
|
|
1234
|
+
const elapsedAfter = running && toolElapsedThreshold !== false ? toolElapsedThreshold : void 0;
|
|
1162
1235
|
const gruppenModus = detailMode === "grouped";
|
|
1163
1236
|
const bloecke = [];
|
|
1164
1237
|
let lastDay;
|
|
1165
1238
|
let gruppe = [];
|
|
1166
1239
|
const schliesseGruppe = () => {
|
|
1167
1240
|
if (gruppe.length > 0) {
|
|
1168
|
-
const
|
|
1241
|
+
const laufenderSchritt = running ? [...gruppe].reverse().find((message) => ["running", "thinking"].includes(stepState(message))) : void 0;
|
|
1169
1242
|
bloecke.push(mitZeit(
|
|
1170
1243
|
gruppenModus ? /* @__PURE__ */ jsx13(
|
|
1171
1244
|
StepGroup,
|
|
1172
1245
|
{
|
|
1173
|
-
|
|
1246
|
+
elapsedAfter,
|
|
1174
1247
|
expandierbar: stepsExpandable,
|
|
1248
|
+
laufenderSchritt,
|
|
1175
1249
|
messages: gruppe,
|
|
1176
1250
|
texts: alleTexte,
|
|
1177
1251
|
toolArgumentsText
|
|
@@ -1180,6 +1254,7 @@ function ChatMessages({
|
|
|
1180
1254
|
) : /* @__PURE__ */ jsx13(
|
|
1181
1255
|
StepRow,
|
|
1182
1256
|
{
|
|
1257
|
+
elapsedAfter,
|
|
1183
1258
|
expandierbar: stepsExpandable,
|
|
1184
1259
|
messages: gruppe,
|
|
1185
1260
|
mitText: detailMode !== "icons",
|
|
@@ -1227,6 +1302,7 @@ function ChatMessages({
|
|
|
1227
1302
|
{
|
|
1228
1303
|
detailMode,
|
|
1229
1304
|
dicht,
|
|
1305
|
+
elapsedAfter,
|
|
1230
1306
|
expandierbar: stepsExpandable,
|
|
1231
1307
|
message,
|
|
1232
1308
|
plain: owner != null && message.sender === owner,
|
|
@@ -1259,8 +1335,10 @@ function ChatMessages({
|
|
|
1259
1335
|
"qsl:[--qsl-fade-edge:calc(100%_-_var(--qsl-composer-height,0px))]",
|
|
1260
1336
|
"qsl:[-webkit-mask-image:linear-gradient(to_bottom,#000_calc(var(--qsl-fade-edge)_-_40px),transparent_calc(var(--qsl-fade-edge)_+_16px))]",
|
|
1261
1337
|
"qsl:[mask-image:linear-gradient(to_bottom,#000_calc(var(--qsl-fade-edge)_-_40px),transparent_calc(var(--qsl-fade-edge)_+_16px))]",
|
|
1262
|
-
"qsl:in-data-[tone=material]:p-0"
|
|
1338
|
+
"qsl:in-data-[tone=material]:p-0",
|
|
1339
|
+
scrollerClassName
|
|
1263
1340
|
),
|
|
1341
|
+
"data-quassel-transcript": "",
|
|
1264
1342
|
onScroll: pruefeEnde,
|
|
1265
1343
|
onWheel: (event) => {
|
|
1266
1344
|
if (!event.ctrlKey && event.deltaY < 0) pauseUp(event.currentTarget, event.target);
|
|
@@ -1310,7 +1388,11 @@ function ChatMessages({
|
|
|
1310
1388
|
scroll.jump(scrollBereich.current);
|
|
1311
1389
|
updateJumpVisibility(scrollBereich.current);
|
|
1312
1390
|
}
|
|
1313
|
-
}, children: /* @__PURE__ */ jsx13(ChevronDownIcon, {}) }) })
|
|
1391
|
+
}, children: /* @__PURE__ */ jsx13(ChevronDownIcon, {}) }) }),
|
|
1392
|
+
dock && offeneAktionen.length > 0 && createPortal(
|
|
1393
|
+
/* @__PURE__ */ jsx13("div", { className: "qsl:flex qsl:flex-col qsl:gap-[var(--qsl-chat-dense-message-gap,8px)] qsl:text-[length:var(--qsl-chat-font-size,13px)] qsl:text-foreground", style: appearanceStyle(appearance), children: offeneAktionen.map((message) => /* @__PURE__ */ jsx13("div", { children: /* @__PURE__ */ jsx13(ActionContent, { action: message.action, onDismissAction, renderAction, text: message.text, texts: alleTexte }) }, message.key)) }),
|
|
1394
|
+
dock
|
|
1395
|
+
)
|
|
1314
1396
|
] });
|
|
1315
1397
|
return /* @__PURE__ */ jsx13(MarkdownLinks, { onLinkClick, children: /* @__PURE__ */ jsx13(MarkdownCodeBlocks, { options: codeBlockOptions, texts: alleTexte, children: verlauf }) });
|
|
1316
1398
|
}
|
|
@@ -1318,6 +1400,7 @@ function StepRow({
|
|
|
1318
1400
|
messages,
|
|
1319
1401
|
mitText,
|
|
1320
1402
|
expandierbar,
|
|
1403
|
+
elapsedAfter,
|
|
1321
1404
|
texts,
|
|
1322
1405
|
toolArgumentsText,
|
|
1323
1406
|
toolLabel
|
|
@@ -1334,6 +1417,7 @@ function StepRow({
|
|
|
1334
1417
|
const content = /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1335
1418
|
thinking ? /* @__PURE__ */ jsx13(SparklesIcon2, { size: 11 }) : /* @__PURE__ */ jsx13(WrenchIcon2, { className: tool?.isError ? "qsl:text-destructive" : void 0, size: 11 }),
|
|
1336
1419
|
mitText && /* @__PURE__ */ jsx13("span", { className: "qsl:min-w-0 qsl:self-baseline qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap", children: label }),
|
|
1420
|
+
mitText && /* @__PURE__ */ jsx13(ToolElapsed, { after: elapsedAfter, className: "qsl:flex-none qsl:self-baseline", message, texts }),
|
|
1337
1421
|
mitText && /* @__PURE__ */ jsx13("span", { className: "qsl:inline-flex qsl:w-2.5 qsl:flex-none qsl:items-center qsl:justify-center qsl:text-success", children: state === "done" && /* @__PURE__ */ jsx13(CheckIcon4, { size: 10 }) })
|
|
1338
1422
|
] });
|
|
1339
1423
|
const classes = cn(chipClasses, !mitText && "qsl:p-1", running && "qsl:animate-fade-pulse qsl:motion-reduce:animate-none");
|
|
@@ -1370,7 +1454,8 @@ function StepRow({
|
|
|
1370
1454
|
}
|
|
1371
1455
|
function StepGroup({
|
|
1372
1456
|
messages,
|
|
1373
|
-
|
|
1457
|
+
laufenderSchritt,
|
|
1458
|
+
elapsedAfter,
|
|
1374
1459
|
expandierbar,
|
|
1375
1460
|
texts,
|
|
1376
1461
|
toolArgumentsText
|
|
@@ -1384,10 +1469,10 @@ function StepGroup({
|
|
|
1384
1469
|
kopf.current?.scrollIntoView({ block: "nearest" });
|
|
1385
1470
|
}
|
|
1386
1471
|
}, [offen]);
|
|
1387
|
-
const
|
|
1472
|
+
const aktiv = laufenderSchritt !== void 0;
|
|
1388
1473
|
const fehler = messages.some((message) => message.tool?.isError);
|
|
1389
1474
|
const anzahl = messages.length === 1 ? texts.stepGroupOne : texts.stepGroupMany.replace("{count}", String(messages.length));
|
|
1390
|
-
const laufend =
|
|
1475
|
+
const laufend = laufenderSchritt && (laufenderSchritt.role === "thinking" ? texts.thinkingChip : laufenderSchritt.tool?.name || laufenderSchritt.text || texts.toolChip);
|
|
1391
1476
|
return /* @__PURE__ */ jsxs6("div", { className: stepClasses, "data-step": "group", children: [
|
|
1392
1477
|
/* @__PURE__ */ jsxs6(
|
|
1393
1478
|
"button",
|
|
@@ -1406,12 +1491,13 @@ function StepGroup({
|
|
|
1406
1491
|
laufend,
|
|
1407
1492
|
" ",
|
|
1408
1493
|
texts.toolRunning
|
|
1409
|
-
] })
|
|
1494
|
+
] }),
|
|
1495
|
+
laufenderSchritt && /* @__PURE__ */ jsx13(ToolElapsed, { after: elapsedAfter, message: laufenderSchritt, texts })
|
|
1410
1496
|
] })
|
|
1411
1497
|
]
|
|
1412
1498
|
}
|
|
1413
1499
|
),
|
|
1414
|
-
offen && /* @__PURE__ */ jsx13("div", { className: "qsl:mt-0.5 qsl:flex qsl:flex-col qsl:gap-0.5 qsl:pl-3", children: messages.map((message) => /* @__PURE__ */ jsx13(TraceLine, { className: "qsl:pl-3", expandierbar, message, texts, toolArgumentsText }, message.key)) }),
|
|
1500
|
+
offen && /* @__PURE__ */ jsx13("div", { className: "qsl:mt-0.5 qsl:flex qsl:flex-col qsl:gap-0.5 qsl:pl-3", children: messages.map((message) => /* @__PURE__ */ jsx13(TraceLine, { className: "qsl:pl-3", elapsedAfter, expandierbar, message, texts, toolArgumentsText }, message.key)) }),
|
|
1415
1501
|
offen && messages.length >= collapseAtBottomFrom && /* @__PURE__ */ jsxs6(
|
|
1416
1502
|
"button",
|
|
1417
1503
|
{
|
|
@@ -1433,6 +1519,7 @@ function StepGroup({
|
|
|
1433
1519
|
function TraceLine({
|
|
1434
1520
|
message,
|
|
1435
1521
|
className,
|
|
1522
|
+
elapsedAfter,
|
|
1436
1523
|
expandierbar,
|
|
1437
1524
|
texts,
|
|
1438
1525
|
toolArgumentsText
|
|
@@ -1446,7 +1533,8 @@ function TraceLine({
|
|
|
1446
1533
|
thinking ? /* @__PURE__ */ jsx13(SparklesIcon2, { className: traceIconClasses, size: 12 }) : /* @__PURE__ */ jsx13(WrenchIcon2, { className: tool?.isError ? traceErrorIconClasses : traceIconClasses, size: 12 }),
|
|
1447
1534
|
/* @__PURE__ */ jsxs6("span", { className: zeile, children: [
|
|
1448
1535
|
message.text,
|
|
1449
|
-
tool && tool.result === void 0 && /* @__PURE__ */ jsx13("span", { className: traceRunningClasses, children: texts.toolRunning })
|
|
1536
|
+
tool && tool.result === void 0 && /* @__PURE__ */ jsx13("span", { className: traceRunningClasses, children: texts.toolRunning }),
|
|
1537
|
+
/* @__PURE__ */ jsx13(ToolElapsed, { after: elapsedAfter, message, texts })
|
|
1450
1538
|
] })
|
|
1451
1539
|
] });
|
|
1452
1540
|
const marks = { "data-compact": "true", "data-kind": thinking ? "thinking" : "tool", "data-step": "line" };
|
|
@@ -1478,11 +1566,21 @@ function TraceLine({
|
|
|
1478
1566
|
)
|
|
1479
1567
|
] });
|
|
1480
1568
|
}
|
|
1569
|
+
function ToolElapsed({ message, after, texts, className = traceRunningClasses }) {
|
|
1570
|
+
const start = stepState(message) === "running" ? messageDate(message.at)?.getTime() : void 0;
|
|
1571
|
+
return after === void 0 || start === void 0 ? null : /* @__PURE__ */ jsx13(Elapsed, { after, className, start, texts });
|
|
1572
|
+
}
|
|
1573
|
+
function Elapsed({ start, after, className, texts }) {
|
|
1574
|
+
const elapsed = useElapsed(start);
|
|
1575
|
+
if (elapsed === void 0 || elapsed < after) return null;
|
|
1576
|
+
return /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", className: cn(className, "qsl:tabular-nums"), "data-step": "elapsed", children: formatElapsed(elapsed, texts) });
|
|
1577
|
+
}
|
|
1481
1578
|
function Bubble({
|
|
1482
1579
|
message,
|
|
1483
1580
|
plain,
|
|
1484
1581
|
detailMode,
|
|
1485
1582
|
dicht,
|
|
1583
|
+
elapsedAfter,
|
|
1486
1584
|
expandierbar,
|
|
1487
1585
|
texts,
|
|
1488
1586
|
toolArgumentsText,
|
|
@@ -1494,23 +1592,24 @@ function Bubble({
|
|
|
1494
1592
|
const schritt = dicht ? denseStepClasses : stepClasses;
|
|
1495
1593
|
if (message.role === "thinking" || message.role === "tool" && message.tool) {
|
|
1496
1594
|
if (detailMode === "compact") {
|
|
1497
|
-
return /* @__PURE__ */ jsx13(TraceLine, { className: schritt, expandierbar, message, texts, toolArgumentsText });
|
|
1595
|
+
return /* @__PURE__ */ jsx13(TraceLine, { className: schritt, elapsedAfter, expandierbar, message, texts, toolArgumentsText });
|
|
1498
1596
|
}
|
|
1499
1597
|
const thinking = message.role === "thinking";
|
|
1500
1598
|
const tool = message.tool;
|
|
1501
1599
|
const icon = thinking ? /* @__PURE__ */ jsx13(SparklesIcon2, { className: traceIconClasses, size: 12 }) : /* @__PURE__ */ jsx13(WrenchIcon2, { className: tool?.isError ? traceErrorIconClasses : traceIconClasses, size: 12 });
|
|
1502
1600
|
const zeile = /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1503
1601
|
message.text,
|
|
1504
|
-
tool && tool.result === void 0 && /* @__PURE__ */ jsx13("span", { className: traceRunningClasses, children: texts.toolRunning })
|
|
1602
|
+
tool && tool.result === void 0 && /* @__PURE__ */ jsx13("span", { className: traceRunningClasses, children: texts.toolRunning }),
|
|
1603
|
+
/* @__PURE__ */ jsx13(ToolElapsed, { after: elapsedAfter, message, texts })
|
|
1505
1604
|
] });
|
|
1506
1605
|
return /* @__PURE__ */ jsxs6("div", { className: cn(traceClasses, schritt), "data-kind": thinking ? "thinking" : "tool", "data-step": "detail", children: [
|
|
1507
1606
|
icon,
|
|
1508
1607
|
/* @__PURE__ */ jsxs6("div", { className: "qsl:min-w-0 qsl:flex-1", children: [
|
|
1509
1608
|
/* @__PURE__ */ jsx13("div", { className: cn(traceLineClasses, thinking && "qsl:font-sans qsl:italic qsl:whitespace-pre-wrap"), children: zeile }),
|
|
1510
1609
|
tool && /* @__PURE__ */ jsxs6("div", { className: "qsl:mt-0.5 qsl:border-l-2 qsl:border-border-soft qsl:pl-2", children: [
|
|
1511
|
-
/* @__PURE__ */ jsx13("pre", { className: "qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-
|
|
1610
|
+
/* @__PURE__ */ jsx13("pre", { className: "qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-meta qsl:leading-[1.375] qsl:break-all qsl:whitespace-pre-wrap qsl:opacity-80", children: toolArgumentsText(tool) }),
|
|
1512
1611
|
tool.result !== void 0 && /* @__PURE__ */ jsx13("pre", { className: cn(
|
|
1513
|
-
"qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-
|
|
1612
|
+
"qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-meta qsl:leading-[1.375] qsl:break-all qsl:whitespace-pre-wrap qsl:opacity-80",
|
|
1514
1613
|
tool.isError && "qsl:text-destructive qsl:opacity-100"
|
|
1515
1614
|
), children: prettyJson(tool.result) })
|
|
1516
1615
|
] })
|
|
@@ -1518,18 +1617,7 @@ function Bubble({
|
|
|
1518
1617
|
] });
|
|
1519
1618
|
}
|
|
1520
1619
|
if (message.role === "action" && message.action) {
|
|
1521
|
-
|
|
1522
|
-
return /* @__PURE__ */ jsx13("div", { className: schritt, children: renderAction?.(action, message.text) ?? /* @__PURE__ */ jsx13(
|
|
1523
|
-
PendingActionCard,
|
|
1524
|
-
{
|
|
1525
|
-
action,
|
|
1526
|
-
dismissedLabel: texts.actionDismissed,
|
|
1527
|
-
dismissLabel: texts.dismissAction,
|
|
1528
|
-
onDismiss: onDismissAction ? () => onDismissAction(action.actionId) : void 0,
|
|
1529
|
-
text: message.text,
|
|
1530
|
-
waitingLabel: texts.pendingAction
|
|
1531
|
-
}
|
|
1532
|
-
) });
|
|
1620
|
+
return /* @__PURE__ */ jsx13("div", { className: schritt, children: /* @__PURE__ */ jsx13(ActionContent, { action: message.action, onDismissAction, renderAction, text: message.text, texts }) });
|
|
1533
1621
|
}
|
|
1534
1622
|
if (message.role === "system") {
|
|
1535
1623
|
return /* @__PURE__ */ jsxs6("div", { className: cn(schritt, "qsl:border-l-2 qsl:border-destructive/50 qsl:pl-3 qsl:text-sm qsl:text-muted-foreground"), "data-message": "system", children: [
|
|
@@ -1545,12 +1633,12 @@ function Bubble({
|
|
|
1545
1633
|
const showSender = bubbleOptions?.showSender ?? (!!message.bubble?.label && !plain);
|
|
1546
1634
|
const content = /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1547
1635
|
showSender && sender && /* @__PURE__ */ jsx13("span", { className: cn(
|
|
1548
|
-
"qsl:mb-[5px] qsl:table qsl:text-
|
|
1636
|
+
"qsl:mb-[5px] qsl:table qsl:text-label qsl:leading-[1.45] qsl:font-semibold",
|
|
1549
1637
|
useBubble && message.bubble && "qsl:rounded-full qsl:border qsl:border-white/30 qsl:bg-black/15 qsl:px-[7px] qsl:py-px qsl:tracking-[0.02em]"
|
|
1550
1638
|
), "data-chat": "sender", children: sender }),
|
|
1551
1639
|
/* @__PURE__ */ jsx13(Markdown, { text: message.text, streaming: message.role === "assistant" && !message.closed }),
|
|
1552
1640
|
/* @__PURE__ */ jsx13(MessageAttachments, { label: texts.attachments, message }),
|
|
1553
|
-
message.steered && /* @__PURE__ */ jsx13("small", { className: "qsl:mt-1 qsl:block qsl:text-
|
|
1641
|
+
message.steered && /* @__PURE__ */ jsx13("small", { className: "qsl:mt-1 qsl:block qsl:text-label qsl:leading-[1.45] qsl:opacity-70", "data-chat": "steered", children: texts.steered }),
|
|
1554
1642
|
/* @__PURE__ */ jsx13(MessageActions, { message, options: messageActions, texts })
|
|
1555
1643
|
] });
|
|
1556
1644
|
const cursor = message.role === "assistant" && message.textCursor ? JSON.stringify(message.textCursor) : void 0;
|
|
@@ -1565,7 +1653,7 @@ function Bubble({
|
|
|
1565
1653
|
children: /* @__PURE__ */ jsx13(
|
|
1566
1654
|
"div",
|
|
1567
1655
|
{
|
|
1568
|
-
className: cn(bubbleBodyClasses, "qsl:group", message.bubble ? "qsl:rounded-lg qsl:text-white qsl:[--qsl-scroll-cover:var(--qsl-primary)]" : "qsl:rounded-[10px_10px_4px_10px] qsl:border qsl:border-border qsl:bg-secondary qsl:text-foreground qsl:[--qsl-scroll-cover:var(--qsl-secondary)] qsl:in-data-[tone=material]:rounded-[9px] qsl:in-data-[tone=material]:border-glass-edge/20 qsl:in-data-[tone=material]:bg-primary/15 qsl:in-data-[tone=material]:text-foreground"),
|
|
1656
|
+
className: cn(bubbleBodyClasses, "qsl:group", message.bubble ? "qsl:rounded-lg qsl:text-white qsl:[--qsl-scroll-cover:var(--qsl-primary)]" : "qsl:rounded-[var(--qsl-bubble-radius,10px_10px_4px_10px)] qsl:border qsl:border-border qsl:bg-secondary qsl:text-foreground qsl:[--qsl-scroll-cover:var(--qsl-secondary)] qsl:in-data-[tone=material]:rounded-[var(--qsl-bubble-radius,9px)] qsl:in-data-[tone=material]:border-glass-edge/20 qsl:in-data-[tone=material]:bg-primary/15 qsl:in-data-[tone=material]:text-foreground"),
|
|
1569
1657
|
"data-tone": message.bubble ? "on-color" : void 0,
|
|
1570
1658
|
style: { background: message.bubble?.color, maxWidth: bubbleOptions?.maxWidth },
|
|
1571
1659
|
children: content
|
|
@@ -1574,6 +1662,25 @@ function Bubble({
|
|
|
1574
1662
|
}
|
|
1575
1663
|
);
|
|
1576
1664
|
}
|
|
1665
|
+
function ActionContent({
|
|
1666
|
+
action,
|
|
1667
|
+
text,
|
|
1668
|
+
texts,
|
|
1669
|
+
renderAction,
|
|
1670
|
+
onDismissAction
|
|
1671
|
+
}) {
|
|
1672
|
+
return renderAction?.(action, text) ?? /* @__PURE__ */ jsx13(
|
|
1673
|
+
PendingActionCard,
|
|
1674
|
+
{
|
|
1675
|
+
action,
|
|
1676
|
+
dismissedLabel: texts.actionDismissed,
|
|
1677
|
+
dismissLabel: texts.dismissAction,
|
|
1678
|
+
onDismiss: onDismissAction ? () => onDismissAction(action.actionId) : void 0,
|
|
1679
|
+
text,
|
|
1680
|
+
waitingLabel: texts.pendingAction
|
|
1681
|
+
}
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1577
1684
|
function MessageAttachments({ message, label }) {
|
|
1578
1685
|
if (!message.attachments?.length) return null;
|
|
1579
1686
|
return /* @__PURE__ */ jsx13("ul", { className: "qsl:mt-2.5 qsl:flex qsl:flex-wrap qsl:gap-2", "aria-label": label, children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsxs6("li", { className: "qsl:relative qsl:flex qsl:w-[190px] qsl:max-w-full qsl:min-w-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-lg qsl:border qsl:border-border qsl:text-sm", children: [
|
|
@@ -1601,6 +1708,7 @@ function ChatPanel({
|
|
|
1601
1708
|
}) {
|
|
1602
1709
|
const wurzel = useRef4(null);
|
|
1603
1710
|
const eingabe = useRef4(null);
|
|
1711
|
+
const [dock, setDock] = useState5(null);
|
|
1604
1712
|
const hasComposer = composer !== void 0;
|
|
1605
1713
|
const scrollOnSendRef = useRef4(scrollOnSend);
|
|
1606
1714
|
const [sendScope] = useState5(() => createChatSendScope(scrollOnSendRef));
|
|
@@ -1613,16 +1721,21 @@ function ChatPanel({
|
|
|
1613
1721
|
if (!element || !rahmen) {
|
|
1614
1722
|
return;
|
|
1615
1723
|
}
|
|
1616
|
-
const messen = () =>
|
|
1724
|
+
const messen = () => {
|
|
1725
|
+
rahmen.style.setProperty("--qsl-composer-height", `${element.offsetHeight}px`);
|
|
1726
|
+
rahmen.style.setProperty("--qsl-panel-height", `${rahmen.offsetHeight}px`);
|
|
1727
|
+
};
|
|
1617
1728
|
const beobachter = new ResizeObserver(messen);
|
|
1618
1729
|
beobachter.observe(element);
|
|
1730
|
+
beobachter.observe(rahmen);
|
|
1619
1731
|
messen();
|
|
1620
1732
|
return () => {
|
|
1621
1733
|
beobachter.disconnect();
|
|
1622
1734
|
rahmen.style.removeProperty("--qsl-composer-height");
|
|
1735
|
+
rahmen.style.removeProperty("--qsl-panel-height");
|
|
1623
1736
|
};
|
|
1624
1737
|
}, [hasComposer]);
|
|
1625
|
-
return /* @__PURE__ */ jsx14(ChatSendContext.Provider, { value: sendScope, children: /* @__PURE__ */ jsxs7(
|
|
1738
|
+
return /* @__PURE__ */ jsx14(ChatSendContext.Provider, { value: sendScope, children: /* @__PURE__ */ jsx14(ChatActionDock.Provider, { value: hasComposer ? dock : void 0, children: /* @__PURE__ */ jsxs7(
|
|
1626
1739
|
"div",
|
|
1627
1740
|
{
|
|
1628
1741
|
className: cn("qsl:relative qsl:flex qsl:min-h-0 qsl:min-w-0 qsl:flex-col qsl:overflow-hidden", className),
|
|
@@ -1643,14 +1756,24 @@ function ChatPanel({
|
|
|
1643
1756
|
},
|
|
1644
1757
|
children: [
|
|
1645
1758
|
children,
|
|
1646
|
-
hasComposer && /* @__PURE__ */
|
|
1759
|
+
hasComposer && /* @__PURE__ */ jsxs7("div", { className: "qsl:absolute qsl:inset-x-0 qsl:bottom-0 qsl:z-[5] qsl:px-[var(--qsl-chat-horizontal-padding,24px)] qsl:pb-3.5 qsl:*:mx-auto qsl:*:max-w-[var(--qsl-chat-content-max-width,none)]", "data-chat": "composer", ref: eingabe, children: [
|
|
1760
|
+
/* @__PURE__ */ jsx14("div", { children: /* @__PURE__ */ jsx14(
|
|
1761
|
+
"div",
|
|
1762
|
+
{
|
|
1763
|
+
className: "qsl:-mx-[16px] qsl:max-h-[calc(var(--qsl-panel-height,100dvh)_/_2)] qsl:overflow-y-auto qsl:px-[16px] qsl:pb-[var(--qsl-chat-message-gap,16px)] qsl:[-webkit-mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,16px)),transparent)] qsl:[mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,16px)),transparent)] qsl:empty:hidden",
|
|
1764
|
+
"data-chat": "actions",
|
|
1765
|
+
ref: setDock
|
|
1766
|
+
}
|
|
1767
|
+
) }),
|
|
1768
|
+
composer
|
|
1769
|
+
] })
|
|
1647
1770
|
]
|
|
1648
1771
|
}
|
|
1649
|
-
) });
|
|
1772
|
+
) }) });
|
|
1650
1773
|
}
|
|
1651
1774
|
|
|
1652
1775
|
// packages/quassel/src/ChatInputToolbar.tsx
|
|
1653
|
-
import { PaperclipIcon, SendIcon, XIcon as
|
|
1776
|
+
import { PaperclipIcon, SendIcon, XIcon as XIcon3 } from "lucide-react";
|
|
1654
1777
|
|
|
1655
1778
|
// packages/quassel/src/ui/useFileInput.ts
|
|
1656
1779
|
import { useRef as useRef5, useState as useState6 } from "react";
|
|
@@ -1702,7 +1825,7 @@ function useFileInput({ disabled, onFiles, onPasteText }) {
|
|
|
1702
1825
|
|
|
1703
1826
|
// packages/quassel/src/ChatInputToolbar.tsx
|
|
1704
1827
|
import { useCallback as useCallback3, useContext as useContext4, useEffect as useEffect5, useImperativeHandle, useLayoutEffect as useLayoutEffect3, useRef as useRef6, useState as useState7 } from "react";
|
|
1705
|
-
import { createPortal } from "react-dom";
|
|
1828
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1706
1829
|
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1707
1830
|
var COMPACT_WIDTH_PX = 480;
|
|
1708
1831
|
var errorClasses = "qsl:px-3 qsl:py-2 qsl:text-sm qsl:text-destructive";
|
|
@@ -1851,7 +1974,7 @@ function ChatInputToolbar({
|
|
|
1851
1974
|
const inputRows = inline || toolbar ? 1 : rows;
|
|
1852
1975
|
const inputMaxRows = inline || toolbar ? 1 : maxRows;
|
|
1853
1976
|
const rootClasses = cn(
|
|
1854
|
-
"qsl:flex qsl:shrink-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-[var(--qsl-input-card-radius
|
|
1977
|
+
"qsl:flex qsl:shrink-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-[var(--qsl-input-card-radius,--theme(--radius-xl))] qsl:border qsl:border-border-strong qsl:bg-background qsl:shadow-bar qsl:transition-colors qsl:focus-within:border-primary",
|
|
1855
1978
|
"qsl:in-data-[tone=material]:rounded-xl qsl:in-data-[tone=material]:border-glass-edge/50 qsl:in-data-[tone=material]:bg-background",
|
|
1856
1979
|
toolbar && "qsl:h-full qsl:min-w-0 qsl:flex-row qsl:items-center qsl:rounded-lg qsl:data-[working=true]:animate-working-pulse qsl:data-[working=true]:border-primary qsl:motion-reduce:data-[working=true]:animate-none",
|
|
1857
1980
|
fileInput.dragging && "qsl:outline-2 qsl:outline-offset-[3px] qsl:outline-dashed qsl:outline-primary"
|
|
@@ -2041,7 +2164,7 @@ function ChatInputToolbar({
|
|
|
2041
2164
|
size: "icon-sm",
|
|
2042
2165
|
title: fillText(alleTexte.removeAttachment, { name: entry.file.name }),
|
|
2043
2166
|
variant: "outline",
|
|
2044
|
-
children: /* @__PURE__ */ jsx15(
|
|
2167
|
+
children: /* @__PURE__ */ jsx15(XIcon3, {})
|
|
2045
2168
|
}
|
|
2046
2169
|
)
|
|
2047
2170
|
] }, entry.id)) });
|
|
@@ -2172,7 +2295,7 @@ function ChatInputToolbar({
|
|
|
2172
2295
|
] }) : input,
|
|
2173
2296
|
toolbar ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
2174
2297
|
/* @__PURE__ */ jsx15("div", { className: "qsl:flex qsl:flex-none qsl:items-center qsl:gap-1 qsl:p-1", children: sendButtons }),
|
|
2175
|
-
detailsContainer &&
|
|
2298
|
+
detailsContainer && createPortal2(details, detailsContainer)
|
|
2176
2299
|
] }) : !inline && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
2177
2300
|
errors,
|
|
2178
2301
|
detailToolbar
|
|
@@ -2283,6 +2406,7 @@ export {
|
|
|
2283
2406
|
encodeAttachment,
|
|
2284
2407
|
fillText,
|
|
2285
2408
|
formatAttachmentSize,
|
|
2409
|
+
formatElapsed,
|
|
2286
2410
|
markdownPlainText,
|
|
2287
2411
|
messageDate,
|
|
2288
2412
|
prettyJson,
|
|
@@ -2290,7 +2414,9 @@ export {
|
|
|
2290
2414
|
timestampDay,
|
|
2291
2415
|
timestampLabel,
|
|
2292
2416
|
useChatAction,
|
|
2417
|
+
useElapsed,
|
|
2293
2418
|
useQuasselComponents,
|
|
2419
|
+
useQuasselPortalContainer,
|
|
2294
2420
|
validateAttachmentSelection
|
|
2295
2421
|
};
|
|
2296
2422
|
//# sourceMappingURL=index.js.map
|