Merge pull request #771 from pikasTech/fix/issue756-playwright-live-errors

fix(web): defer workbench fetches until auth ready
This commit is contained in:
Lyon
2026-06-03 18:34:28 +08:00
committed by GitHub
4 changed files with 11 additions and 5 deletions
+4
View File
@@ -36,6 +36,8 @@ for (const file of requiredFiles) {
console.log("hwlab-cloud-web check: React module assets present");
const html = readWeb("index.html");
const appTsx = readWeb("src/App.tsx");
const apiClientSource = readWeb("src/services/api/client.ts");
const appSource = readCloudWebAppSource(rootDir);
const css = readWeb("src/styles/workbench.css");
@@ -53,6 +55,8 @@ assertIncludes(appSource, "DevicePodSidebar", "Device Pod sidebar component must
assertIncludes(appSource, "CommandBar", "command bar component must exist");
assertIncludes(appSource, "SkillsView", "skills component must exist");
assertIncludes(appSource, "SettingsView", "settings component must exist");
assertIncludes(appTsx, "useWorkbenchStore(auth.authState === \"authenticated\")", "Workbench data requests must wait until auth is authenticated");
assertIncludes(apiClientSource, "adapter: (): Promise<ApiResult<LiveProbePayload>> => fetchJson(\"/v1/rpc/system.health\", { method: \"POST\"", "adapter health must use POST /v1/rpc/system.health");
assertIncludes(appSource, "id=\"command-input\"", "React runtime must render command input selector");
assertIncludes(appSource, "id=\"conversation-list\"", "React runtime must render conversation list selector");
assertIncludes(appSource, "id=\"device-pod-sidebar\"", "React runtime must render Device Pod sidebar selector");
+1 -1
View File
@@ -16,7 +16,7 @@ import { fetchText } from "./services/api/client";
export function App(): ReactElement {
const auth = useAuth();
const store = useWorkbenchStore();
const store = useWorkbenchStore(auth.authState === "authenticated");
const [route, setRoute] = useState<RouteId>(() => routeFromLocation());
const [leftCollapsed, setLeftCollapsed] = useState(false);
const [rightCollapsed, setRightCollapsed] = useState(false);
@@ -87,7 +87,7 @@ export const api = {
healthLive: (): Promise<ApiResult<LiveProbePayload>> => fetchJson("/health/live", { timeoutMs: 12000, timeoutName: "health/live" }),
health: (): Promise<ApiResult<LiveProbePayload>> => fetchJson("/health", { timeoutMs: 12000, timeoutName: "health" }),
restIndex: (): Promise<ApiResult<LiveProbePayload>> => fetchJson("/v1", { timeoutMs: 12000, timeoutName: "REST index" }),
adapter: (): Promise<ApiResult<LiveProbePayload>> => fetchJson("/v1/rpc/system.health", { timeoutMs: 12000, timeoutName: "adapter" }),
adapter: (): Promise<ApiResult<LiveProbePayload>> => fetchJson("/v1/rpc/system.health", { method: "POST", body: JSON.stringify({}), timeoutMs: 12000, timeoutName: "adapter" }),
devicePods: (): Promise<ApiResult<DevicePodListResponse>> => fetchJson("/v1/device-pods", { timeoutMs: 12000, timeoutName: "Device Pods" }),
devicePodStatus: (devicePodId: string): Promise<ApiResult<DevicePodStatusResponse>> => fetchJson(`/v1/device-pods/${encodeURIComponent(devicePodId)}/status`, { timeoutMs: 12000, timeoutName: "Device Pod status" }),
devicePodEvents: (devicePodId: string): Promise<ApiResult<DevicePodEventsResponse>> => fetchJson(`/v1/device-pods/${encodeURIComponent(devicePodId)}/events?limit=120`, { timeoutMs: 12000, timeoutName: "Device Pod events" }),
+5 -3
View File
@@ -95,7 +95,7 @@ export interface WorkbenchStore {
selectDevicePod(devicePodId: string): void;
}
export function useWorkbenchStore(): WorkbenchStore {
export function useWorkbenchStore(enabled: boolean): WorkbenchStore {
const [state, dispatch] = useReducer(reducer, initialState);
const activeConversationId = firstNonEmptyString(
@@ -144,14 +144,16 @@ export function useWorkbenchStore(): WorkbenchStore {
}, [state.selectedDevicePodId]);
useEffect(() => {
if (!enabled) return;
void hydrate();
}, [hydrate]);
}, [enabled, hydrate]);
useEffect(() => {
if (!enabled) return;
void refreshLive();
const timer = window.setInterval(() => void refreshLive(), 30_000);
return () => window.clearInterval(timer);
}, [refreshLive]);
}, [enabled, refreshLive]);
const createSession = useCallback(async () => {
const workspace = await ensureWorkspace(state.workspace);