feat(web): add dialectic reasoning playground

Lets users fire one query at every Honcho reasoning level (minimal / low /
medium / high / max) in parallel and compare answers + latency side-by-side
in a 5-column grid.

- New route: /workspaces/:ws/peers/:peer/playground
- New component: DialecticPlayground with per-column state, level checkboxes
  to skip expensive levels, and a single Run button that fans out via
  Promise.all
- Extends useChat() to accept an optional reasoning_level parameter (was
  hardcoded to "low")
- Adds a Playground button next to Chat on the peer detail page
- Tests cover the parallel fan-out (peak concurrency = 5, no serial
  awaiting) and per-column latency measurement
- Screenshot Playwright spec (idle / mid-flight / settled) drives the
  images in docs/screenshots/ — regen with PLAYWRIGHT_BASE_URL=... pnpm
  exec playwright test e2e/playground.screenshots.spec.ts
This commit is contained in:
Ben Sheridan Edwards
2026-05-24 18:31:16 +01:00
committed by Offending Commit
parent 6960bf4ffe
commit 2340e65028
10 changed files with 644 additions and 16 deletions

View File

@@ -263,7 +263,21 @@ export function useSearchPeer(workspaceId: string, peerId: string) {
});
}
export function useChat(workspaceId: string, peerId: string) {
export type ReasoningLevel = "minimal" | "low" | "medium" | "high" | "max";
export const REASONING_LEVELS: readonly ReasoningLevel[] = [
"minimal",
"low",
"medium",
"high",
"max",
] as const;
export function useChat(
workspaceId: string,
peerId: string,
reasoningLevel: ReasoningLevel = "low",
) {
const qc = useQueryClient();
return useMutation({
mutationFn: async (message: string) => {
@@ -271,7 +285,7 @@ export function useChat(workspaceId: string, peerId: string) {
"/v3/workspaces/{workspace_id}/peers/{peer_id}/chat",
{
params: { path: { workspace_id: workspaceId, peer_id: peerId } },
body: { query: message, stream: false, reasoning_level: "low" },
body: { query: message, stream: false, reasoning_level: reasoningLevel },
},
);
return data ?? err(error);