mirror of
https://github.com/andrewyng/openworker.git
synced 2026-09-11 14:50:14 +00:00
Show reasoning traces: live Thinking block + persisted disclosure
New reasoning_delta event; traces persist as a display sidecar stripped from provider feeds. Sources: compat vendors' reasoning_content and Gemini thought summaries (include_thoughts). Live-verified on GLM via Together and Gemini 3; Gemini tool loops stay healthy.
This commit is contained in:
@@ -648,6 +648,27 @@ export async function mockApi(page: import("@playwright/test").Page) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
// A reasoning model's turn: thinking deltas tick in slowly, then the answer —
|
||||
// the assistant_message carries the full trace like the real engine's payload.
|
||||
if (/think hard/i.test(msg.text)) {
|
||||
const thoughts = ["Weighing options. ", "Comparing tradeoffs. ", "Settling it. "];
|
||||
let tick = 0;
|
||||
const timer = setInterval(() => {
|
||||
if (tick < thoughts.length) {
|
||||
send("reasoning_delta", { text: thoughts[tick] });
|
||||
tick += 1;
|
||||
return;
|
||||
}
|
||||
clearInterval(timer);
|
||||
send("assistant_delta", { text: "Decision made." });
|
||||
send("assistant_message", {
|
||||
text: "Decision made.",
|
||||
reasoning: thoughts.join(""),
|
||||
});
|
||||
send("turn_done");
|
||||
}, 120);
|
||||
return;
|
||||
}
|
||||
// A turn that dies on a provider error; the follow-up {type:"retry"} recovers.
|
||||
if (/fail the turn/i.test(msg.text)) {
|
||||
send("error", { error: "model unreachable" });
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Model-layer roadmap item 4 (2026-07-22): reasoning traces. Live turn shows a quiet
|
||||
// pulsing "Thinking…" disclosure that streams the trace; once the message finalizes the
|
||||
// trace folds into a collapsed "Thought process" disclosure on the answer bubble.
|
||||
import { expect } from "@playwright/test";
|
||||
import { test } from "./fixtures";
|
||||
|
||||
test("thinking streams live, then persists as a collapsed disclosure on the answer", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/");
|
||||
await page.getByText("Draft the launch note").first().click();
|
||||
const box = page.getByPlaceholder(/Ask the coworker/);
|
||||
await box.fill("think hard about this");
|
||||
await box.press("Enter");
|
||||
|
||||
// Live phase: the Thinking… block is up while deltas tick in; expanding shows the trace.
|
||||
await expect(page.getByText("Thinking…").first()).toBeVisible({ timeout: 10_000 });
|
||||
await page.getByTestId("thinking-toggle").click();
|
||||
await expect(page.getByTestId("thinking-body")).toContainText("Weighing options.");
|
||||
|
||||
// Finalized: the answer bubble carries a collapsed "Thought process" disclosure.
|
||||
await expect(page.getByText("Decision made.").first()).toBeVisible({ timeout: 10_000 });
|
||||
await expect(page.getByText("Thinking…")).toHaveCount(0);
|
||||
const toggle = page.getByTestId("thinking-toggle");
|
||||
await expect(toggle).toHaveText(/Thought process/);
|
||||
await expect(page.getByTestId("thinking-body")).toHaveCount(0); // collapsed by default
|
||||
await toggle.click();
|
||||
await expect(page.getByTestId("thinking-body")).toContainText(
|
||||
"Weighing options. Comparing tradeoffs. Settling it.",
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user