diff --git a/src/ui/card-persistence.ts b/src/ui/card-persistence.ts index 7093f064..cf7ef3ed 100644 --- a/src/ui/card-persistence.ts +++ b/src/ui/card-persistence.ts @@ -11,7 +11,10 @@ export interface OpenAIWidgetStateBridge { toolOutput?: unknown; toolResponseMetadata?: unknown; widgetState?: unknown; - setWidgetState?: (state: unknown) => void; + // Kept for host capability diagnostics only. DevSpace deliberately treats + // ChatGPT widget state as read-only: authoritative card persistence lives in + // the server-side card store, avoiding host-side widget_state write races. + setWidgetState?: (state: unknown) => Promise | void; } export interface OpenAICardReference { diff --git a/src/ui/workspace-app.tsx b/src/ui/workspace-app.tsx index 7798ed06..063e05b1 100644 --- a/src/ui/workspace-app.tsx +++ b/src/ui/workspace-app.tsx @@ -24,7 +24,6 @@ import { cardInvocationFromHostContext, cardReferenceFromOpenAIHost, persistedCardFromOpenAIHost, - widgetStateWithPersistedCard, type OpenAIWidgetStateBridge, } from "./card-persistence.js"; import { @@ -83,7 +82,7 @@ if (!maybeAppRoot) { const appRoot = maybeAppRoot; const CARD_PROBE_PREFIX = "[DevSpace card-probe]"; -const CARD_PROBE_BUILD = "card-race-v3"; +const CARD_PROBE_BUILD = "card-race-v4"; void boot(); @@ -139,7 +138,6 @@ async function boot(): Promise { const nextCard = { ...structured, tool }; card = nextCard; cardOrigin = "tool-result"; - persistCard(nextCard); expanded = isInitiallyExpandedCard(nextCard); reviewFilesExpanded = false; openWorkspaceInstructionKey = null; @@ -398,7 +396,6 @@ function restoreStoredCard( openWorkspaceInstructionKey = null; showAvailableWorkspaceInstructions = false; errorMessage = null; - persistCard(restored); logCardProbe("store-restore-hit", { trigger, tool: restored.tool, @@ -463,33 +460,6 @@ function clearCardForRestore(): void { errorMessage = null; } -function persistCard(nextCard: ToolResultCard): void { - const bridge = openAIWidgetBridge(); - if (typeof bridge?.setWidgetState !== "function") { - logCardProbe("host-persist-skip", { - tool: nextCard.tool, - cardId: nextCard.cardId, - }); - return; - } - - try { - bridge.setWidgetState(widgetStateWithPersistedCard(bridge.widgetState, nextCard)); - logCardProbe("host-persist-called", { - tool: nextCard.tool, - cardId: nextCard.cardId, - }); - } catch (persistError) { - logCardProbe("host-persist-failed", { - tool: nextCard.tool, - cardId: nextCard.cardId, - error: persistError instanceof Error ? persistError.message : String(persistError), - }); - // ChatGPT widget persistence is an optional host extension. A host-side - // failure must never prevent the portable MCP Apps card from rendering. - } -} - function probeRecord(value: unknown): Record | undefined { return value && typeof value === "object" && !Array.isArray(value) ? value as Record