diff --git a/apps/web/src/assistant/lifecycle-service.ts b/apps/web/src/assistant/lifecycle-service.ts index d639f982b4f..1537351651d 100644 --- a/apps/web/src/assistant/lifecycle-service.ts +++ b/apps/web/src/assistant/lifecycle-service.ts @@ -83,6 +83,13 @@ export interface LifecycleServiceInputs { * behavior. Optional so existing `setInputs` callers/tests need no change. */ selectedPlatformAssistantId?: string | null; + /** + * Whether the org store has hydrated (or no platform session exists). + * Platform API calls require the Vellum-Organization-Id header; + * `respondToInputs` defers `checkAssistant` until this is true. + * Mirrors `useIsOrgReady()` from the React layer. + */ + isOrgReady?: boolean; } const NOOP_REDIRECT = (_: string) => {}; @@ -194,6 +201,7 @@ class AssistantLifecycleService { if (this.inputs.hasPlatformSession) { setSelfHostedConnection(null); } + if (!this.inputs.isOrgReady) return; await this.checkAssistant(); } diff --git a/apps/web/src/assistant/use-lifecycle.ts b/apps/web/src/assistant/use-lifecycle.ts index 57a91cdfbb7..93ef900f648 100644 --- a/apps/web/src/assistant/use-lifecycle.ts +++ b/apps/web/src/assistant/use-lifecycle.ts @@ -19,6 +19,7 @@ import { lifecycleService } from "@/assistant/lifecycle-service"; import { useAssistantQuery } from "@/assistant/queries"; import { isGatewayAuthMode } from "@/lib/auth/gateway-session"; import { isLocalMode } from "@/lib/local-mode"; +import { useIsOrgReady } from "@/hooks/use-is-org-ready"; import { isAuthenticated, type SessionStatus } from "@/stores/session-status"; import { useClientFeatureFlagStore } from "@/stores/client-feature-flag-store"; import { useResolvedAssistantsStore } from "@/stores/resolved-assistants-store"; @@ -52,13 +53,20 @@ export function useAssistantLifecycle({ }: UseAssistantLifecycleOptions): void { const queryClient = useQueryClient(); + const isOrgReady = useIsOrgReady(); + const currentOrganizationId = + useOrganizationStore.use.currentOrganizationId(); + // Whether to query the server-side status at all. Gateway-auth // mode and "local mode without platform session" short-circuit // to local states without ever calling /assistant/. + // Platform API calls require the Vellum-Organization-Id header; + // wait for the org store to resolve before firing them. const shouldQueryServer = isAuthenticated(sessionStatus) && !isGatewayAuthMode() && - (hasPlatformSession || !isLocalMode()); + (hasPlatformSession || !isLocalMode()) && + isOrgReady; // Which platform assistant the user has selected, gated by the // multi-platform-assistant flag. When the flag is off (or no @@ -67,8 +75,6 @@ export function useAssistantLifecycle({ // pre-multi-assistant behavior. const multiAssistantEnabled = useClientFeatureFlagStore.use.multiPlatformAssistant(); - const currentOrganizationId = - useOrganizationStore.use.currentOrganizationId(); const byOrg = useResolvedAssistantsStore.use.selectedPlatformAssistantByOrg(); const selectedPlatformAssistantId = @@ -97,6 +103,7 @@ export function useAssistantLifecycle({ resolveOnboardingRedirect, queryClient, selectedPlatformAssistantId, + isOrgReady, }); void lifecycleService.respondToInputs(); }, [ @@ -108,6 +115,7 @@ export function useAssistantLifecycle({ resolveOnboardingRedirect, queryClient, selectedPlatformAssistantId, + isOrgReady, ]); // Hand poll results to the service — it decides whether to diff --git a/apps/web/src/root-layout.tsx b/apps/web/src/root-layout.tsx index e2f22dd4620..1bb21fc6b76 100644 --- a/apps/web/src/root-layout.tsx +++ b/apps/web/src/root-layout.tsx @@ -41,6 +41,7 @@ import { useElectronFeatureFlagBridge } from "@/runtime/electron-feature-flags"; import { TimezoneSync } from "@/components/timezone-sync"; import { retireAssistant } from "@/assistant/retire-service"; import { selectPlatformAssistant } from "@/assistant/select-platform-assistant"; +import { useIsOrgReady } from "@/hooks/use-is-org-ready"; import { CreateAssistantDialog } from "@/components/create-assistant-dialog"; import { ConfirmDialog } from "@vellumai/design-library/components/confirm-dialog"; import { toast } from "@vellumai/design-library/components/toast"; @@ -90,7 +91,8 @@ export function RootLayout() { const isSessionInitializing = useIsSessionInitializing(); const hasPlatformSession = useHasPlatformSession(); const isNonProduction = useEnvironmentStore.use.isNonProduction(); - useClientFeatureFlagSync(hasPlatformSession && !isSessionInitializing); + const isOrgReady = useIsOrgReady(); + useClientFeatureFlagSync(hasPlatformSession && !isSessionInitializing && isOrgReady); useAssistantLifecycle({ sessionStatus, isRetired: false,