fix(webui): show quoted context after follow-up send (#5071)
This commit is contained in:
@@ -112,6 +112,32 @@ describe("MessageBubble", () => {
|
||||
expect(screen.queryByRole("button", { name: "Fork" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("styles only generated quoted context in user messages", () => {
|
||||
const message: UIMessage = {
|
||||
id: "u-quote",
|
||||
role: "user",
|
||||
content: "> [!QUOTE]\n> selected assistant excerpt\n\nWhat about this?",
|
||||
createdAt: Date.now(),
|
||||
};
|
||||
|
||||
const { rerender } = render(<MessageBubble message={message} />);
|
||||
|
||||
const quote = screen.getByLabelText("Quoted context");
|
||||
expect(quote).toHaveTextContent("selected assistant excerpt");
|
||||
expect(screen.queryByText("Quoted context")).not.toBeInTheDocument();
|
||||
expect(screen.getByText("What about this?")).toBeInTheDocument();
|
||||
|
||||
rerender(
|
||||
<MessageBubble
|
||||
message={{
|
||||
...message,
|
||||
content: "> manually typed quote\n\nWhat about this?",
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
expect(screen.queryByLabelText("Quoted context")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("copies user messages from the shared message action", async () => {
|
||||
const writeText = vi.fn().mockResolvedValue(undefined);
|
||||
Object.defineProperty(navigator, "clipboard", {
|
||||
|
||||
@@ -1600,6 +1600,25 @@ describe("useNanobotStream", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("inlines quoted context into the optimistic and outbound user message", () => {
|
||||
const fake = fakeClient();
|
||||
const { result } = renderHook(() => useNanobotStream("chat-quote", EMPTY_MESSAGES), {
|
||||
wrapper: wrap(fake.client),
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.send("What about this?", undefined, {
|
||||
quotedContext: "selected assistant excerpt",
|
||||
});
|
||||
});
|
||||
|
||||
const expectedContent = "> [!QUOTE]\n> selected assistant excerpt\n\nWhat about this?";
|
||||
expect(result.current.messages[0].content).toBe(expectedContent);
|
||||
const outbound = fake.client.sendMessage.mock.calls.at(-1)!;
|
||||
expect(outbound[1]).toBe(expectedContent);
|
||||
expect(outbound[3]).not.toHaveProperty("quotedContext");
|
||||
});
|
||||
|
||||
it("attaches assistant media_urls to complete messages", () => {
|
||||
const fake = fakeClient();
|
||||
const { result } = renderHook(() => useNanobotStream("chat-m", EMPTY_MESSAGES), {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
formatQuotedUserMessage,
|
||||
parseQuotedUserMessage,
|
||||
} from "@/lib/user-message-quote";
|
||||
|
||||
describe("user message quotes", () => {
|
||||
it("round-trips multiline quoted context through the message body", () => {
|
||||
const content = formatQuotedUserMessage(
|
||||
"What does this mean?",
|
||||
"first quoted line\n\nsecond quoted line",
|
||||
);
|
||||
|
||||
expect(content).toBe(
|
||||
"> [!QUOTE]\n> first quoted line\n>\n> second quoted line\n\nWhat does this mean?",
|
||||
);
|
||||
expect(parseQuotedUserMessage(content)).toEqual({
|
||||
quotedContext: "first quoted line\n\nsecond quoted line",
|
||||
content: "What does this mean?",
|
||||
});
|
||||
});
|
||||
|
||||
it("leaves ordinary messages and manual blockquotes unchanged", () => {
|
||||
const manualBlockquote = "> manually typed quote\n\nordinary message";
|
||||
|
||||
expect(parseQuotedUserMessage(manualBlockquote)).toEqual({
|
||||
quotedContext: null,
|
||||
content: manualBlockquote,
|
||||
});
|
||||
});
|
||||
|
||||
it("does not place quoted context ahead of slash commands", () => {
|
||||
expect(formatQuotedUserMessage("/model", "selected answer excerpt")).toBe("/model");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user