mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-11 02:31:38 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28450db9a2 |
No files matched your search
@@ -680,6 +680,7 @@ function Stream({ loadError, task, entries, subagent, onOpenSubagent, finding, f
|
||||
const turns = useMemo(() => (entries && !subagent ? turnNumbers(entries) : null), [entries, subagent]);
|
||||
const replies = useMemo(() => (entries && !subagent ? replyTurns(entries) : null), [entries, subagent]);
|
||||
const times = useMemo(() => (entries && !subagent ? replyTimes(entries) : null), [entries, subagent]);
|
||||
const lastReply = useMemo(() => entries?.findLastIndex((e) => e.type === "agent" && e.text.trim()), [entries]);
|
||||
const busy = subagent ? subagentWorking(subagent.status) : isBusy(task.status);
|
||||
const lastIndex = entries ? entries.length - 1 : -1;
|
||||
// Keep the row stable when earlier history is prepended; its author can move with the work.
|
||||
@@ -707,12 +708,13 @@ function Stream({ loadError, task, entries, subagent, onOpenSubagent, finding, f
|
||||
turnCount={turns?.size ?? 0}
|
||||
reply={replies?.get(row.index)}
|
||||
time={times?.get(row.index) ?? null}
|
||||
showFooter={subagent ? row.index === lastReply : !!replies?.has(row.index)}
|
||||
working={row.index === lastIndex && busy}
|
||||
onOpenSubagent={onOpenSubagent}
|
||||
onDiagramDrawn={onDiagramDrawn}
|
||||
/>
|
||||
),
|
||||
[task, turns, replies, times, lastIndex, busy, onOpenSubagent, onDiagramDrawn],
|
||||
[task, turns, replies, times, subagent, lastReply, lastIndex, busy, onOpenSubagent, onDiagramDrawn],
|
||||
);
|
||||
return (
|
||||
<div
|
||||
@@ -1083,6 +1085,7 @@ const Entry = memo(function Entry({
|
||||
turnCount,
|
||||
reply,
|
||||
time,
|
||||
showFooter,
|
||||
working,
|
||||
onOpenSubagent,
|
||||
onDiagramDrawn,
|
||||
@@ -1095,6 +1098,7 @@ const Entry = memo(function Entry({
|
||||
reply?: ReplyTurn;
|
||||
/** When the turn this reply answered was asked and finished. */
|
||||
time?: ReplyTimes | null;
|
||||
showFooter: boolean;
|
||||
working: boolean;
|
||||
onOpenSubagent: (id: string) => void;
|
||||
onDiagramDrawn: () => void;
|
||||
@@ -1116,10 +1120,12 @@ const Entry = memo(function Entry({
|
||||
actions={false}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.messageFooter}>
|
||||
<MessageTime sentMs={time?.sentMs ?? null} doneMs={time?.doneMs ?? null} at="done" />
|
||||
<ReplyActions text={entry.text} task={task} reply={reply} turnCount={turnCount} />
|
||||
</div>
|
||||
{showFooter && (
|
||||
<div className={styles.messageFooter}>
|
||||
<MessageTime sentMs={time?.sentMs ?? null} doneMs={time?.doneMs ?? null} at="done" />
|
||||
<ReplyActions text={entry.text} task={task} reply={reply} turnCount={turnCount} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
case "thought":
|
||||
|
||||
@@ -158,7 +158,8 @@ describe("conversation rows", () => {
|
||||
expect(author.parentElement?.nextElementSibling?.firstElementChild).toHaveClass(styles.agentMessage!);
|
||||
const quote = within(stream()).getAllByRole("button", { name: "Quote Reply" });
|
||||
const copy = within(stream()).getAllByRole("button", { name: "Copy Markdown" });
|
||||
expect(quote).toHaveLength(3);
|
||||
expect(quote).toHaveLength(2);
|
||||
expect(copy).toHaveLength(2);
|
||||
for (const button of [...quote, ...copy]) {
|
||||
expect(button.textContent).toBe("");
|
||||
expect(button.querySelector("svg path")).not.toBeNull();
|
||||
@@ -209,26 +210,27 @@ describe("conversation rows", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it("anchors every agent footer with its time before the hover actions", async () => {
|
||||
it("shows the turn time and actions only below its final nonempty reply", async () => {
|
||||
backend.entries.set("A", [
|
||||
{ type: "user", text: "Question", attachments: [], steered: false, sentMs: 1000, doneMs: 13000 },
|
||||
{ type: "agent", text: "First reply" },
|
||||
tool("read"),
|
||||
{ type: "agent", text: "Final reply" },
|
||||
{ type: "agent", text: " " },
|
||||
]);
|
||||
useAgents.setState({ entries: new Map(backend.entries) });
|
||||
render(<SessionEditor input={input("A")} />);
|
||||
await screen.findByText("Final reply");
|
||||
const messages = stream().querySelectorAll(`.${styles.agentMessage}`);
|
||||
expect(messages).toHaveLength(2);
|
||||
for (const message of messages) {
|
||||
const [card, footer] = message.children;
|
||||
expect(card).toHaveClass(styles.agentCard!);
|
||||
expect(footer).toHaveClass(styles.messageFooter!);
|
||||
expect(footer?.firstElementChild).toHaveClass(styles.messageTime!);
|
||||
expect(footer?.firstElementChild).toHaveTextContent("12s");
|
||||
expect(footer?.lastElementChild).toHaveClass(styles.messageActions!);
|
||||
}
|
||||
expect(messages).toHaveLength(3);
|
||||
expect(messages[0]?.querySelector(`.${styles.messageFooter}`)).toBeNull();
|
||||
expect(messages[2]?.querySelector(`.${styles.messageFooter}`)).toBeNull();
|
||||
const [card, footer] = messages[1]!.children;
|
||||
expect(card).toHaveClass(styles.agentCard!);
|
||||
expect(footer).toHaveClass(styles.messageFooter!);
|
||||
expect(footer?.firstElementChild).toHaveClass(styles.messageTime!);
|
||||
expect(footer?.firstElementChild).toHaveTextContent("12s");
|
||||
expect(footer?.lastElementChild).toHaveClass(styles.messageActions!);
|
||||
expect(stream().querySelector(`.${styles.userMessage} > .${styles.messageFooter}`)).not.toBeNull();
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user