mirror of
https://github.com/andrewyng/openworker.git
synced 2026-09-03 13:00:37 +00:00
gui: reload coworkers after health, not only at mount
The mount-time persona fetch loses the race to the sidecar boot, leaving the composer picker empty all session while Settings looked fine.
This commit is contained in:
@@ -42,3 +42,34 @@ test("model picker recovers when settings fetches die during sidecar boot", asyn
|
||||
});
|
||||
await expect(page.getByTestId("models-loading")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("coworker picker recovers when the persona fetch dies during sidecar boot", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Same cold-start shape as above, for /v1/personas (owner-hit 2026-08-13, packaged app):
|
||||
// the mount-time fetch loses to the sidecar boot and its only other trigger is
|
||||
// PERSONAS_CHANGED, so the composer's picker stayed empty for the WHOLE session — while
|
||||
// Settings ▸ Coworkers (mounted later) listed everything and looked healthy.
|
||||
let sidecarUp = false;
|
||||
await page.route("**/v1/health", async (route) => {
|
||||
await new Promise((r) => setTimeout(r, 700));
|
||||
sidecarUp = true;
|
||||
await route.fallback();
|
||||
});
|
||||
await page.route("**/v1/personas", async (route) => {
|
||||
if (route.request().method() === "GET" && !sidecarUp) {
|
||||
await route.abort();
|
||||
return;
|
||||
}
|
||||
await route.fallback();
|
||||
});
|
||||
|
||||
await page.goto("/");
|
||||
await page.getByText("New session").first().click();
|
||||
await page.getByTestId("coworker-chip").click();
|
||||
|
||||
// The menu must list real coworkers, not just its Import/Manage footer.
|
||||
const menu = page.locator(".setup-menu");
|
||||
await expect(menu.getByText("Code Coworker")).toBeVisible({ timeout: 10_000 });
|
||||
await expect(menu.getByTestId("import-coworker")).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -338,14 +338,16 @@ export function App() {
|
||||
// Persona metadata drives workspace behavior by FAMILY, not by hardcoded id (so a DevOps/SecOps
|
||||
// code-family persona gates a folder like Code, and a knowledge persona starts orphan like Cowork).
|
||||
const [personas, setPersonas] = useState<Persona[] | null>(null);
|
||||
const loadPersonas = useCallback(() => {
|
||||
getPersonas().then(setPersonas).catch(() => {});
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const load = () => getPersonas().then(setPersonas).catch(() => {});
|
||||
load();
|
||||
loadPersonas();
|
||||
// The composer's coworker picker is always mounted on a fresh session — refetch on
|
||||
// mutations (enable/install from Settings) instead of going stale.
|
||||
window.addEventListener(PERSONAS_CHANGED, load);
|
||||
return () => window.removeEventListener(PERSONAS_CHANGED, load);
|
||||
}, []);
|
||||
window.addEventListener(PERSONAS_CHANGED, loadPersonas);
|
||||
return () => window.removeEventListener(PERSONAS_CHANGED, loadPersonas);
|
||||
}, [loadPersonas]);
|
||||
const personaOf = (a: string) => personas?.find((p) => p.id === a);
|
||||
|
||||
// Pending Inbox items for the ACTIVE session — surfaced inline above the composer so an
|
||||
@@ -505,6 +507,11 @@ export function App() {
|
||||
// on a cold start that left "Loading models…" stuck until the user visited
|
||||
// Settings (owner-hit 2026-07-23). Health just answered, so this one lands.
|
||||
loadSettings();
|
||||
// Same race, same fix: the mount-time persona fetch loses to the sidecar boot in
|
||||
// the packaged app, and its only other trigger is PERSONAS_CHANGED — so the
|
||||
// composer's coworker picker stayed empty for the whole session while Settings
|
||||
// (mounted later) looked fine (owner-hit 2026-08-13).
|
||||
loadPersonas();
|
||||
if (!cancelled) setBooting(false);
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
Reference in New Issue
Block a user