fix electron desktop ai runtime fallback detection

This commit is contained in:
dirtydishes 2026-05-20 20:11:37 -04:00
parent a54e847c8e
commit d15f96d7be
4 changed files with 390 additions and 47 deletions

View file

@ -19,6 +19,20 @@ import {
} from "./desktop-ai-panels";
describe("desktop ai runtime detection", () => {
const createBridge = (getState: () => Promise<ReturnType<typeof createUnavailableState>>) => ({
ai: {
getState,
loginWithBrowser: async () => {},
loginWithDeviceCode: async () => {},
cancelLogin: async () => {},
logout: async () => {},
updatePreferences: async () => {},
runTask: async () => ({ taskId: "task-1" }),
cancelTask: async () => {},
subscribe: () => () => {},
},
});
it("recognizes the explicit desktop preload marker before the bridge is available", () => {
const runtime = resolveDesktopAiRuntime({
islandflowDesktopRuntime: {
@ -73,6 +87,88 @@ describe("desktop ai runtime detection", () => {
expect(runtime.bridgeAvailable).toBe(true);
expect(runtime.bridge).not.toBeNull();
});
it("keeps desktop runtime when the bridge exists before ai state resolves", () => {
let resolveState: ((value: ReturnType<typeof createUnavailableState>) => void) | null = null;
const pending = new Promise<ReturnType<typeof createUnavailableState>>((resolve) => {
resolveState = resolve;
});
const runtime = resolveDesktopAiRuntime({
islandflowDesktopRuntime: {
app: "islandflow",
shell: "electron",
},
islandflowDesktop: createBridge(() => pending),
navigator: { userAgent: "Mozilla/5.0 Safari/537.36" },
});
expect(runtime.shellAvailable).toBe(true);
expect(runtime.bridgeAvailable).toBe(true);
expect(runtime.bridge).not.toBeNull();
expect(
requireDesktopActionCopy(
runtime.shellAvailable,
runtime.bridgeAvailable,
false,
),
).toContain("Connect a ChatGPT or Codex account");
resolveState?.(
createUnavailableState({
shellAvailable: true,
bridgeAvailable: true,
}),
);
});
it("keeps bridge-specific recovery copy when bridge state loading fails", async () => {
const runtime = resolveDesktopAiRuntime({
islandflowDesktopRuntime: {
app: "islandflow",
shell: "electron",
},
islandflowDesktop: createBridge(async () => {
throw new Error("state failed");
}),
navigator: { userAgent: "Mozilla/5.0 Safari/537.36" },
});
expect(runtime.shellAvailable).toBe(true);
expect(runtime.bridgeAvailable).toBe(true);
expect(createUnavailableState(runtime).transportError).toContain(
"initial state could not be read",
);
expect(
requireDesktopActionCopy(
runtime.shellAvailable,
runtime.bridgeAvailable,
false,
),
).not.toContain("Open Islandflow Desktop");
});
it("flips from browser runtime to desktop runtime when the marker appears later", () => {
const host: {
islandflowDesktopRuntime?: { app?: string | null; shell?: string | null };
navigator: { userAgent: string };
} = {
navigator: { userAgent: "Mozilla/5.0 Safari/537.36" },
};
const initialRuntime = resolveDesktopAiRuntime(host);
expect(initialRuntime.shellAvailable).toBe(false);
expect(initialRuntime.bridgeAvailable).toBe(false);
host.islandflowDesktopRuntime = {
app: "islandflow",
shell: "electron",
};
const nextRuntime = resolveDesktopAiRuntime(host);
expect(nextRuntime.shellAvailable).toBe(true);
expect(nextRuntime.bridgeAvailable).toBe(false);
});
});
describe("desktop ai unavailable state", () => {