quassel 0.4.2 → 0.4.3
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/ChatMessages.d.ts +3 -2
- package/README.md +1 -0
- package/TranscriptModeSwitch.d.ts +8 -0
- package/index.d.ts +2 -1
- package/index.js +50 -8
- package/index.js.map +4 -4
- package/package.json +1 -1
- package/texts.d.ts +3 -1
- package/types.d.ts +1 -0
package/ChatMessages.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CSSProperties, ReactNode } from "react";
|
|
2
|
-
import { ChatAnnouncement, DetailMode, Message, PendingAction, ToolInfo } from "./types";
|
|
2
|
+
import { ChatAnnouncement, DetailMode, Message, PendingAction, ToolInfo, TranscriptMode } from "./types";
|
|
3
3
|
import { ChatTexts } from "./texts";
|
|
4
4
|
import { type LinkClickHandler } from "./Markdown";
|
|
5
5
|
import { type ChatAppearance, type TimestampOptions, type CodeBlockOptions, type BubbleOptions, type MessageActionsOptions } from "./options";
|
|
@@ -7,11 +7,12 @@ import { type ChatAppearance, type TimestampOptions, type CodeBlockOptions, type
|
|
|
7
7
|
* The transcript: its own scroll container with autoscroll while you are at the bottom, and a
|
|
8
8
|
* jump-to-end button as soon as you are reading. Usable read-only without a composer.
|
|
9
9
|
*/
|
|
10
|
-
export declare function ChatMessages({ messages, owner, detailMode, running, working, stepsExpandable, groupsExpandable, texts, toolArgumentsText, renderTool, renderAction, onDismissAction, onLinkClick, emptyState, className, scrollerClassName, showTimestamps, announce, scrollerRef, maxWidth, horizontalPadding, jumpToEndThreshold, appearance, timestampOptions, codeBlockOptions, bubbleOptions, messageActions, toolElapsedThreshold, }: {
|
|
10
|
+
export declare function ChatMessages({ messages, owner, detailMode, transcriptMode, running, working, stepsExpandable, groupsExpandable, texts, toolArgumentsText, renderTool, renderAction, onDismissAction, onLinkClick, emptyState, className, scrollerClassName, showTimestamps, announce, scrollerRef, maxWidth, horizontalPadding, jumpToEndThreshold, appearance, timestampOptions, codeBlockOptions, bubbleOptions, messageActions, toolElapsedThreshold, }: {
|
|
11
11
|
messages: Message[];
|
|
12
12
|
/** Contributions with this Message.sender appear without a speech bubble; null keeps the message defaults. */
|
|
13
13
|
owner?: string | null;
|
|
14
14
|
detailMode?: DetailMode;
|
|
15
|
+
transcriptMode?: TranscriptMode;
|
|
15
16
|
running?: boolean;
|
|
16
17
|
working?: ReactNode;
|
|
17
18
|
/** false = thinking and tool steps cannot be expanded (no popover). */
|
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ variables too.
|
|
|
43
43
|
- Streaming-safe Markdown (tables, code with copy button, lists) via Streamdown.
|
|
44
44
|
- Steering: typing while a turn runs sends into it; stop, retry and failed-send recovery built in.
|
|
45
45
|
- Attachments by button, drag and drop or paste, with previews and size limits.
|
|
46
|
+
- Condensed conversation: all user inputs and the latest answer between them, independently of tool/thinking detail.
|
|
46
47
|
- Timestamps, day separators, message actions, configurable bubbles and appearance.
|
|
47
48
|
- Screen reader friendly: the transcript is not a live region; finished replies and new
|
|
48
49
|
actions are announced once, with the host in control of the wording.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type TranscriptMode } from "./types";
|
|
2
|
+
import { type ChatTexts } from "./texts";
|
|
3
|
+
export declare function TranscriptModeSwitch({ mode, onChange, texts, className }: {
|
|
4
|
+
mode: TranscriptMode;
|
|
5
|
+
onChange: (mode: TranscriptMode) => void;
|
|
6
|
+
texts?: Partial<ChatTexts>;
|
|
7
|
+
className?: string;
|
|
8
|
+
}): import("react").JSX.Element;
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Role, ToolInfo, PendingAction, Message, ChatEvent, ChatTextCursor, ChatJournalCursor, ChatAttachment, ChatAttachmentInput, ChatAttachmentCapabilities, ChatStartupStatus, DetailMode, StepState, ChatAnnouncement, } from "./types";
|
|
1
|
+
export type { Role, ToolInfo, PendingAction, Message, ChatEvent, ChatTextCursor, ChatJournalCursor, ChatAttachment, ChatAttachmentInput, ChatAttachmentCapabilities, ChatStartupStatus, DetailMode, TranscriptMode, StepState, ChatAnnouncement, } from "./types";
|
|
2
2
|
export { applyEvent, prettyJson, compactToolLine, stepState } from "./types";
|
|
3
3
|
export type { ChatTexts } from "./texts";
|
|
4
4
|
export { defaultTexts, fillText } from "./texts";
|
|
@@ -6,6 +6,7 @@ export { ChatMessages } from "./ChatMessages";
|
|
|
6
6
|
export { ChatPanel } from "./ChatPanel";
|
|
7
7
|
export { ChatInputToolbar, type ChatInputHandle, type ToolbarAction } from "./ChatInputToolbar";
|
|
8
8
|
export { DetailModeSwitch, DETAIL_MODES, detailModeLabel } from "./DetailModeSwitch";
|
|
9
|
+
export { TranscriptModeSwitch } from "./TranscriptModeSwitch";
|
|
9
10
|
export { TimestampSwitch } from "./TimestampSwitch";
|
|
10
11
|
export { Markdown, MarkdownCodeBlocks, MarkdownLinks, markdownPlainText, type LinkClickHandler } from "./Markdown";
|
|
11
12
|
export { MessageActions } from "./MessageActions";
|
package/index.js
CHANGED
|
@@ -51,6 +51,8 @@ var defaultTexts = {
|
|
|
51
51
|
detailModeGrouped: "grouped",
|
|
52
52
|
detailModeCompact: "single line",
|
|
53
53
|
detailModeFull: "everything",
|
|
54
|
+
showAllMessages: "Show intermediate replies",
|
|
55
|
+
showLatestExchange: "Show latest reply between inputs",
|
|
54
56
|
showTimestamps: "Show timestamps",
|
|
55
57
|
hideTimestamps: "Hide timestamps",
|
|
56
58
|
copyMessage: "Copy message",
|
|
@@ -1097,6 +1099,7 @@ function ChatMessages({
|
|
|
1097
1099
|
messages,
|
|
1098
1100
|
owner,
|
|
1099
1101
|
detailMode = "current",
|
|
1102
|
+
transcriptMode = "all",
|
|
1100
1103
|
running: running2 = false,
|
|
1101
1104
|
working,
|
|
1102
1105
|
stepsExpandable = true,
|
|
@@ -1123,6 +1126,21 @@ function ChatMessages({
|
|
|
1123
1126
|
messageActions,
|
|
1124
1127
|
toolElapsedThreshold = 3e3
|
|
1125
1128
|
}) {
|
|
1129
|
+
const selected = useMemo3(() => {
|
|
1130
|
+
if (transcriptMode === "all") return messages;
|
|
1131
|
+
const answers = /* @__PURE__ */ new Set();
|
|
1132
|
+
let hasAnswer = false;
|
|
1133
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
1134
|
+
const message = messages[index];
|
|
1135
|
+
if (message.role === "user") {
|
|
1136
|
+
hasAnswer = false;
|
|
1137
|
+
} else if (message.role === "assistant" && !hasAnswer && (message.text.trim() !== "" || message.attachments?.length)) {
|
|
1138
|
+
answers.add(message);
|
|
1139
|
+
hasAnswer = true;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
return messages.filter((message) => message.role !== "assistant" || answers.has(message));
|
|
1143
|
+
}, [messages, transcriptMode]);
|
|
1126
1144
|
const allTexts = { ...defaultTexts, ...texts };
|
|
1127
1145
|
const { Button: Button2 } = useQuasselComponents();
|
|
1128
1146
|
const scrollArea = useRef3(null);
|
|
@@ -1150,8 +1168,8 @@ function ChatMessages({
|
|
|
1150
1168
|
if (announce2 === false || due.length > maxAnnouncementsAtOnce) {
|
|
1151
1169
|
return;
|
|
1152
1170
|
}
|
|
1153
|
-
due.map((message) => announce2 ? announce2({ kind: message.role === "action" ? "action" : "reply", message }) : markdownPlainText(message.text)).forEach((text) => text && announce(text));
|
|
1154
|
-
}, [messages, running2, announce2]);
|
|
1171
|
+
due.filter((message) => selected.includes(message)).map((message) => announce2 ? announce2({ kind: message.role === "action" ? "action" : "reply", message }) : markdownPlainText(message.text)).forEach((text) => text && announce(text));
|
|
1172
|
+
}, [messages, selected, running2, announce2]);
|
|
1155
1173
|
const updateJumpVisibility = useCallback2((viewport) => {
|
|
1156
1174
|
if (viewport.clientHeight > 0) setShowJumpToEnd(viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop > jumpToEndThreshold);
|
|
1157
1175
|
}, [jumpToEndThreshold]);
|
|
@@ -1203,8 +1221,8 @@ function ChatMessages({
|
|
|
1203
1221
|
});
|
|
1204
1222
|
const visible = useMemo3(
|
|
1205
1223
|
() => {
|
|
1206
|
-
const lastNonUser =
|
|
1207
|
-
return
|
|
1224
|
+
const lastNonUser = selected.reduce((last, message, index) => message.role === "user" ? last : index, -1);
|
|
1225
|
+
return selected.filter((message, index) => {
|
|
1208
1226
|
if (dock !== void 0 && isOpenAction(message)) {
|
|
1209
1227
|
return false;
|
|
1210
1228
|
}
|
|
@@ -1220,7 +1238,7 @@ function ChatMessages({
|
|
|
1220
1238
|
return true;
|
|
1221
1239
|
});
|
|
1222
1240
|
},
|
|
1223
|
-
[
|
|
1241
|
+
[selected, detailMode, running2, dock]
|
|
1224
1242
|
);
|
|
1225
1243
|
const openActions = dock ? messages.filter(isOpenAction) : [];
|
|
1226
1244
|
const withTime = (content, key, at, dense = false) => showTimestamps ? /* @__PURE__ */ jsxs6("div", { className: cn("qsl:flex qsl:items-baseline qsl:gap-2", dense ? denseStepClasses : stepClasses), children: [
|
|
@@ -2352,14 +2370,37 @@ function DetailModeSwitch({
|
|
|
2352
2370
|
return /* @__PURE__ */ jsx16(Button2, { "aria-label": title, className, onClick: () => onChange(next2), size: "icon-sm", title, variant: "ghost", children: /* @__PURE__ */ jsx16(Icon, {}) });
|
|
2353
2371
|
}
|
|
2354
2372
|
|
|
2373
|
+
// packages/quassel/src/TranscriptModeSwitch.tsx
|
|
2374
|
+
import { MessagesSquareIcon, MessageSquareIcon } from "lucide-react";
|
|
2375
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2376
|
+
function TranscriptModeSwitch({ mode, onChange, texts, className }) {
|
|
2377
|
+
const labels = { ...defaultTexts, ...texts };
|
|
2378
|
+
const { Button: Button2 } = useQuasselComponents();
|
|
2379
|
+
const latest = mode === "latest";
|
|
2380
|
+
const title = latest ? labels.showAllMessages : labels.showLatestExchange;
|
|
2381
|
+
return /* @__PURE__ */ jsx17(
|
|
2382
|
+
Button2,
|
|
2383
|
+
{
|
|
2384
|
+
"aria-label": title,
|
|
2385
|
+
"aria-pressed": latest,
|
|
2386
|
+
className,
|
|
2387
|
+
onClick: () => onChange(latest ? "all" : "latest"),
|
|
2388
|
+
size: "icon-sm",
|
|
2389
|
+
title,
|
|
2390
|
+
variant: "ghost",
|
|
2391
|
+
children: latest ? /* @__PURE__ */ jsx17(MessageSquareIcon, {}) : /* @__PURE__ */ jsx17(MessagesSquareIcon, {})
|
|
2392
|
+
}
|
|
2393
|
+
);
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2355
2396
|
// packages/quassel/src/TimestampSwitch.tsx
|
|
2356
2397
|
import { ClockFadingIcon, ClockIcon } from "lucide-react";
|
|
2357
|
-
import { jsx as
|
|
2398
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
2358
2399
|
function TimestampSwitch({ showTimestamps, onChange, texts, className }) {
|
|
2359
2400
|
const labels = { ...defaultTexts, ...texts };
|
|
2360
2401
|
const { Button: Button2 } = useQuasselComponents();
|
|
2361
2402
|
const title = showTimestamps ? labels.hideTimestamps : labels.showTimestamps;
|
|
2362
|
-
return /* @__PURE__ */
|
|
2403
|
+
return /* @__PURE__ */ jsx18(
|
|
2363
2404
|
Button2,
|
|
2364
2405
|
{
|
|
2365
2406
|
"aria-label": title,
|
|
@@ -2369,7 +2410,7 @@ function TimestampSwitch({ showTimestamps, onChange, texts, className }) {
|
|
|
2369
2410
|
size: "icon-sm",
|
|
2370
2411
|
title,
|
|
2371
2412
|
variant: "ghost",
|
|
2372
|
-
children: showTimestamps ? /* @__PURE__ */
|
|
2413
|
+
children: showTimestamps ? /* @__PURE__ */ jsx18(ClockIcon, {}) : /* @__PURE__ */ jsx18(ClockFadingIcon, {})
|
|
2373
2414
|
}
|
|
2374
2415
|
);
|
|
2375
2416
|
}
|
|
@@ -2390,6 +2431,7 @@ export {
|
|
|
2390
2431
|
QuasselProvider,
|
|
2391
2432
|
StepPopover,
|
|
2392
2433
|
TimestampSwitch,
|
|
2434
|
+
TranscriptModeSwitch,
|
|
2393
2435
|
WorkingScenes,
|
|
2394
2436
|
announce,
|
|
2395
2437
|
appearanceStyle,
|