style: reformat ChatStream/ChatView (line-width normalization) from review pass
This commit is contained in:
@@ -158,7 +158,9 @@ describe("Bubble", () => {
|
|||||||
expect(screen.getByText("$ ls -la")).toBeInTheDocument();
|
expect(screen.getByText("$ ls -la")).toBeInTheDocument();
|
||||||
expect(screen.getByText("finished")).toBeInTheDocument();
|
expect(screen.getByText("finished")).toBeInTheDocument();
|
||||||
|
|
||||||
const summary = screen.getByText("$ ls -la").closest("summary") as HTMLElement;
|
const summary = screen
|
||||||
|
.getByText("$ ls -la")
|
||||||
|
.closest("summary") as HTMLElement;
|
||||||
const card = summary.closest("details") as HTMLDetailsElement;
|
const card = summary.closest("details") as HTMLDetailsElement;
|
||||||
expect(card.open).toBe(false);
|
expect(card.open).toBe(false);
|
||||||
await userEvent.click(summary);
|
await userEvent.click(summary);
|
||||||
@@ -1029,7 +1031,12 @@ describe("unified tool card", () => {
|
|||||||
expect(unqueue).toHaveBeenCalledWith(0);
|
expect(unqueue).toHaveBeenCalledWith(0);
|
||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
stream({ messages: [msg({ role: "user", text: "hi" })], busy: true, queued: [], unqueue }),
|
stream({
|
||||||
|
messages: [msg({ role: "user", text: "hi" })],
|
||||||
|
busy: true,
|
||||||
|
queued: [],
|
||||||
|
unqueue,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
expect(screen.queryByText("next msg")).toBeNull();
|
expect(screen.queryByText("next msg")).toBeNull();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -147,9 +147,7 @@ function oneLine(text: string): string {
|
|||||||
* (which carries the output preview) is already rendered */
|
* (which carries the output preview) is already rendered */
|
||||||
function resultSkipped(m: ChatMessage, tools: Map<string, ToolState>): boolean {
|
function resultSkipped(m: ChatMessage, tools: Map<string, ToolState>): boolean {
|
||||||
return (
|
return (
|
||||||
m.role === "toolResult" &&
|
m.role === "toolResult" && m.toolCallId !== null && tools.has(m.toolCallId)
|
||||||
m.toolCallId !== null &&
|
|
||||||
tools.has(m.toolCallId)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,9 +600,7 @@ export default function ChatStream({
|
|||||||
const q: string = query.trim().toLowerCase();
|
const q: string = query.trim().toLowerCase();
|
||||||
if (q.length === 0) return [];
|
if (q.length === 0) return [];
|
||||||
return messages
|
return messages
|
||||||
.filter(
|
.filter((m) => !resultSkipped(m, tools) && searchHaystack(m).includes(q))
|
||||||
(m) => !resultSkipped(m, tools) && searchHaystack(m).includes(q),
|
|
||||||
)
|
|
||||||
.map((m) => m.key);
|
.map((m) => m.key);
|
||||||
}, [messages, tools, query]);
|
}, [messages, tools, query]);
|
||||||
|
|
||||||
|
|||||||
+10
-27
@@ -142,15 +142,11 @@ export default function ChatView({ store, pushToast }: Props) {
|
|||||||
(incoming: EventFrame[]): void => {
|
(incoming: EventFrame[]): void => {
|
||||||
setEvents((prev) => {
|
setEvents((prev) => {
|
||||||
const merged = mergeEvents(prev, incoming);
|
const merged = mergeEvents(prev, incoming);
|
||||||
lastSeqRef.current = Math.max(
|
lastSeqRef.current = Math.max(lastSeqRef.current, lastPersistedSeq(merged));
|
||||||
lastSeqRef.current,
|
|
||||||
lastPersistedSeq(merged),
|
|
||||||
);
|
|
||||||
return merged;
|
return merged;
|
||||||
});
|
});
|
||||||
// a finished run means usage changed server-side
|
// a finished run means usage changed server-side
|
||||||
if (incoming.some((e) => e.type === EventType.AgentSettled))
|
if (incoming.some((e) => e.type === EventType.AgentSettled)) refreshStats();
|
||||||
refreshStats();
|
|
||||||
},
|
},
|
||||||
[refreshStats],
|
[refreshStats],
|
||||||
);
|
);
|
||||||
@@ -229,8 +225,7 @@ export default function ChatView({ store, pushToast }: Props) {
|
|||||||
const toolNow: string | undefined = [...chat.tools.values()]
|
const toolNow: string | undefined = [...chat.tools.values()]
|
||||||
.filter((t) => t.running)
|
.filter((t) => t.running)
|
||||||
.map((t) => t.name)[0];
|
.map((t) => t.name)[0];
|
||||||
const titleClaim: string | null =
|
const titleClaim: string | null = busy
|
||||||
busy
|
|
||||||
? streaming
|
? streaming
|
||||||
? `${label} · writing…`
|
? `${label} · writing…`
|
||||||
: toolNow === undefined
|
: toolNow === undefined
|
||||||
@@ -279,9 +274,7 @@ export default function ChatView({ store, pushToast }: Props) {
|
|||||||
const t = e.target;
|
const t = e.target;
|
||||||
if (
|
if (
|
||||||
t instanceof HTMLElement &&
|
t instanceof HTMLElement &&
|
||||||
(t.tagName === "INPUT" ||
|
(t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)
|
||||||
t.tagName === "TEXTAREA" ||
|
|
||||||
t.isContentEditable)
|
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -404,10 +397,7 @@ export default function ChatView({ store, pushToast }: Props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const pickModel = async (
|
const pickModel = async (provider: string, modelId: string): Promise<void> => {
|
||||||
provider: string,
|
|
||||||
modelId: string,
|
|
||||||
): Promise<void> => {
|
|
||||||
if (switching) return;
|
if (switching) return;
|
||||||
setSwitching(true);
|
setSwitching(true);
|
||||||
try {
|
try {
|
||||||
@@ -494,8 +484,7 @@ export default function ChatView({ store, pushToast }: Props) {
|
|||||||
}
|
}
|
||||||
// empty composer + history: ArrowUp recalls the last sent message
|
// empty composer + history: ArrowUp recalls the last sent message
|
||||||
if (e.key === ARROW_UP_KEY && draft.length === 0) {
|
if (e.key === ARROW_UP_KEY && draft.length === 0) {
|
||||||
const last: string | undefined =
|
const last: string | undefined = sentRef.current[sentRef.current.length - 1];
|
||||||
sentRef.current[sentRef.current.length - 1];
|
|
||||||
if (last !== undefined) {
|
if (last !== undefined) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setDraft(last);
|
setDraft(last);
|
||||||
@@ -601,15 +590,13 @@ export default function ChatView({ store, pushToast }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{stats !== null &&
|
{stats !== null && (stats.inputTokens > 0 || stats.outputTokens > 0) && (
|
||||||
(stats.inputTokens > 0 || stats.outputTokens > 0) && (
|
|
||||||
<span
|
<span
|
||||||
className="usage-chip"
|
className="usage-chip"
|
||||||
title={`↑${stats.inputTokens.toLocaleString()} ↓${stats.outputTokens.toLocaleString()} · ${stats.turns} turns · $${stats.totalCost.toFixed(2)}`}
|
title={`↑${stats.inputTokens.toLocaleString()} ↓${stats.outputTokens.toLocaleString()} · ${stats.turns} turns · $${stats.totalCost.toFixed(2)}`}
|
||||||
>
|
>
|
||||||
↑{formatTokens(stats.inputTokens)} ↓
|
↑{formatTokens(stats.inputTokens)} ↓{formatTokens(stats.outputTokens)} ·{" "}
|
||||||
{formatTokens(stats.outputTokens)} · {stats.turns} turns · $
|
{stats.turns} turns · ${stats.totalCost.toFixed(2)}
|
||||||
{stats.totalCost.toFixed(2)}
|
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
@@ -641,11 +628,7 @@ export default function ChatView({ store, pushToast }: Props) {
|
|||||||
⋯
|
⋯
|
||||||
</button>
|
</button>
|
||||||
{menuOpen && (
|
{menuOpen && (
|
||||||
<div
|
<div className="chat-menu" role="menu" aria-label="Session actions">
|
||||||
className="chat-menu"
|
|
||||||
role="menu"
|
|
||||||
aria-label="Session actions"
|
|
||||||
>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="chat-menu-item"
|
className="chat-menu-item"
|
||||||
|
|||||||
Reference in New Issue
Block a user