Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/screenshots/live-dream-progress/active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/live-dream-progress/idle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/live-dream-progress/stalled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 99 additions & 0 deletions packages/web/scripts/screenshot-dream-progress.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env node
/**
* Capture documentation screenshots for the Dream Progress panel.
*
* The dev server must already be running at the URL passed in via PREVIEW_URL
* (defaults to http://localhost:5178). The /dream-progress showcase route is
* DEV-only and renders three variants of the panel against mock data.
*
* Usage:
* PREVIEW_URL=http://localhost:5178 OUT_DIR=../../docs/screenshots/live-dream-progress \
* node scripts/screenshot-dream-progress.mjs
*/
import { mkdir } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { chromium } from "@playwright/test";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const PREVIEW_URL = process.env.PREVIEW_URL ?? "http://localhost:5178";
const OUT_DIR = path.resolve(
__dirname,
process.env.OUT_DIR ?? "../../../docs/screenshots/live-dream-progress",
);

async function main() {
await mkdir(OUT_DIR, { recursive: true });
const browser = await chromium.launch();
const context = await browser.newContext({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 2,
colorScheme: "dark",
});
const page = await context.newPage();

// Seed localStorage with a fake instance so the root redirect doesn't kick
// us to the settings page. The showcase doesn't actually make any network
// requests — it renders against in-memory mock data.
await page.addInitScript(() => {
localStorage.setItem(
"openconcho:instances",
JSON.stringify({
instances: [
{
id: "inst_dev_demo",
name: "Demo (mock)",
baseUrl: "http://localhost:9999",
token: "",
},
],
activeId: "inst_dev_demo",
}),
);
});

await page.goto(`${PREVIEW_URL}/dream-progress`, { waitUntil: "networkidle" });
await page.waitForSelector('[data-testid="dream-progress-panel"]');
// Let framer-motion entrance animations settle.
await page.waitForTimeout(600);

// Full showcase — top-to-bottom view of all three variants.
await page.screenshot({
path: path.join(OUT_DIR, "overview.png"),
fullPage: true,
});

// Variant: idle
{
const handle = await page.locator("section").nth(0);
await handle.scrollIntoViewIfNeeded();
await page.waitForTimeout(150);
await handle.screenshot({ path: path.join(OUT_DIR, "idle.png") });
}

// Variant: active (with per-session breakdown)
{
const handle = await page.locator("section").nth(1);
await handle.scrollIntoViewIfNeeded();
await page.waitForTimeout(150);
await handle.screenshot({ path: path.join(OUT_DIR, "active.png") });
}

// Variant: stalled (>30m without forward progress)
{
const handle = await page.locator("section").nth(2);
await handle.scrollIntoViewIfNeeded();
await page.waitForTimeout(150);
await handle.screenshot({ path: path.join(OUT_DIR, "stalled.png") });
}

await browser.close();
console.log(`Saved screenshots to ${OUT_DIR}`);
}

main().catch((err) => {
console.error(err);
process.exit(1);
});
18 changes: 17 additions & 1 deletion packages/web/src/api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ export function useScheduleDream(workspaceId: string) {
});
}

import type { components } from "./schema.d.ts";

type QueueStatusBody = components["schemas"]["QueueStatus"];

// Poll faster while work is in flight so users can watch dreams/representations
// progress; back off to a slow heartbeat when idle. The TanStack Query callback
// form re-reads the cached value each cycle, so the interval adapts on its own.
export const QUEUE_REFETCH_ACTIVE_MS = 2500;
export const QUEUE_REFETCH_IDLE_MS = 10_000;

export function pickQueueRefetchInterval(data: QueueStatusBody | undefined): number {
if (!data) return QUEUE_REFETCH_IDLE_MS;
const active = (data.in_progress_work_units ?? 0) + (data.pending_work_units ?? 0);
return active > 0 ? QUEUE_REFETCH_ACTIVE_MS : QUEUE_REFETCH_IDLE_MS;
}

export function useQueueStatus(workspaceId: string) {
return useQuery({
queryKey: QK.queueStatus(workspaceId),
Expand All @@ -96,7 +112,7 @@ export function useQueueStatus(workspaceId: string) {
return data ?? err(error);
},
enabled: Boolean(workspaceId),
refetchInterval: 10_000,
refetchInterval: (query) => pickQueueRefetchInterval(query.state.data),
});
}

Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/components/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export function Dashboard() {
<Activity className="w-4 h-4" style={{ color: "var(--accent)" }} strokeWidth={1.5} />
<SectionHeading className="mb-0">Queue Status</SectionHeading>
<span className="text-xs ml-1" style={{ color: "var(--text-4)" }}>
all workspaces · updates every 10s
all workspaces · live polling
</span>
</div>

Expand Down
Loading
Loading