diff --git a/packages/ui/src/features/pi-sessions/PiSessionView.tsx b/packages/ui/src/features/pi-sessions/PiSessionView.tsx index 0e2ac2c9a5..934adccfc1 100644 --- a/packages/ui/src/features/pi-sessions/PiSessionView.tsx +++ b/packages/ui/src/features/pi-sessions/PiSessionView.tsx @@ -23,13 +23,13 @@ import type { AgentConversationEvent } from "@posthog/shared"; import { useUsageLimitStore } from "@posthog/ui/features/billing/usageLimitStore"; import { PromptInput } from "@posthog/ui/features/message-editor/components/PromptInput"; import { useDraftStore } from "@posthog/ui/features/message-editor/draftStore"; -import { CloudInitializingView } from "@posthog/ui/features/sessions/components/CloudInitializingView"; import { CloudConnectionBanner, CloudStreamDisconnectedBanner, } from "@posthog/ui/features/sessions/components/CloudSessionLifecycle"; import { ChatThread } from "@posthog/ui/features/sessions/components/chat-thread/ChatThread"; import type { PromptRecallHandler } from "@posthog/ui/features/sessions/components/chat-thread/composerPromptRecall"; +import { SessionInitializingView } from "@posthog/ui/features/sessions/components/SessionInitializingView"; import { CHAT_CONTENT_MAX_WIDTH } from "@posthog/ui/features/sessions/constants"; import { useMessagingModeStore } from "@posthog/ui/features/sessions/messagingModeStore"; import { useWorkspace } from "@posthog/ui/features/workspace/useWorkspace"; @@ -53,9 +53,14 @@ const log = logger.scope("pi-session-view"); interface PiSessionViewProps { taskId: string; taskRunId?: string; + isCloud: boolean; } -export function PiSessionView({ taskId, taskRunId }: PiSessionViewProps) { +export function PiSessionView({ + taskId, + taskRunId, + isCloud, +}: PiSessionViewProps) { const piSessionController = useService( PI_SESSION_CONTROLLER, ); @@ -304,11 +309,13 @@ export function PiSessionView({ taskId, taskRunId }: PiSessionViewProps) { ); const sessionAvailable = session.connectionState === "connected" || hasTranscript; + const executionTarget = isCloud ? "cloud" : "local"; if (isConnecting && !hasTranscript) { return ( - diff --git a/packages/ui/src/features/sessions/components/SessionInitializingView.test.tsx b/packages/ui/src/features/sessions/components/SessionInitializingView.test.tsx new file mode 100644 index 0000000000..211a7b5425 --- /dev/null +++ b/packages/ui/src/features/sessions/components/SessionInitializingView.test.tsx @@ -0,0 +1,50 @@ +import { Theme } from "@radix-ui/themes"; +import { act, render, screen } from "@testing-library/react"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { SessionInitializingView } from "./SessionInitializingView"; + +afterEach(() => { + vi.useRealTimers(); +}); + +describe("SessionInitializingView", () => { + it.each([ + { + executionTarget: "local" as const, + heading: "Starting Pi…", + subtitle: "Connecting to Pi on this device.", + }, + { + executionTarget: "cloud" as const, + heading: "Getting things ready…", + subtitle: "Connecting to your cloud runner.", + }, + { + executionTarget: "cloud" as const, + cloudStatus: "in_progress" as const, + heading: "Starting the sandbox…", + subtitle: "Connecting to your cloud runner.", + }, + ])( + "shows $executionTarget connection copy", + ({ executionTarget, cloudStatus, heading, subtitle }) => { + vi.useFakeTimers(); + + render( + + + , + ); + + act(() => { + vi.advanceTimersByTime(2000); + }); + + expect(screen.getByText(heading)).toBeInTheDocument(); + expect(screen.getByText(subtitle)).toBeInTheDocument(); + }, + ); +}); diff --git a/packages/ui/src/features/sessions/components/CloudInitializingView.tsx b/packages/ui/src/features/sessions/components/SessionInitializingView.tsx similarity index 78% rename from packages/ui/src/features/sessions/components/CloudInitializingView.tsx rename to packages/ui/src/features/sessions/components/SessionInitializingView.tsx index 8e77036a09..7ee16c3277 100644 --- a/packages/ui/src/features/sessions/components/CloudInitializingView.tsx +++ b/packages/ui/src/features/sessions/components/SessionInitializingView.tsx @@ -4,18 +4,26 @@ import { Flex, Text } from "@radix-ui/themes"; import { useEffect, useState } from "react"; import zenHedgehog from "../../../assets/images/zen.png"; -interface CloudInitializingViewProps { - cloudStatus: TaskRunStatus | null; +interface SessionInitializingViewProps { + executionTarget: "cloud" | "local"; + cloudStatus?: TaskRunStatus | null; heading?: string; subtitle?: string; } const REVEAL_DELAY_MS = 2000; -function copyFor(cloudStatus: TaskRunStatus | null): { - heading: string; - subtitle: string; -} { +function copyFor( + executionTarget: "cloud" | "local", + cloudStatus: TaskRunStatus | null | undefined, +): { heading: string; subtitle: string } { + if (executionTarget === "local") { + return { + heading: "Starting Pi…", + subtitle: "Connecting to Pi on this device.", + }; + } + switch (cloudStatus) { case "queued": return { @@ -35,12 +43,13 @@ function copyFor(cloudStatus: TaskRunStatus | null): { } } -export function CloudInitializingView({ +export function SessionInitializingView({ + executionTarget, cloudStatus, heading, subtitle, -}: CloudInitializingViewProps) { - const copy = copyFor(cloudStatus); +}: SessionInitializingViewProps) { + const copy = copyFor(executionTarget, cloudStatus); const visibleHeading = heading ?? copy.heading; const visibleSubtitle = subtitle ?? copy.subtitle; diff --git a/packages/ui/src/features/sessions/components/SessionView.tsx b/packages/ui/src/features/sessions/components/SessionView.tsx index 07d97dd6d0..6b2172d55e 100644 --- a/packages/ui/src/features/sessions/components/SessionView.tsx +++ b/packages/ui/src/features/sessions/components/SessionView.tsx @@ -23,7 +23,6 @@ import { useDraftStore } from "@posthog/ui/features/message-editor/draftStore"; import { useAutoFocusOnTyping } from "@posthog/ui/features/message-editor/useAutoFocusOnTyping"; import { resolveAndAttachDroppedFiles } from "@posthog/ui/features/message-editor/utils/persistFile"; import { PermissionSelector } from "@posthog/ui/features/permissions/PermissionSelector"; -import { CloudInitializingView } from "@posthog/ui/features/sessions/components/CloudInitializingView"; import { CloudStreamDisconnectedBanner, ConnectingToAgent, @@ -39,6 +38,7 @@ import { PlanStatusBar } from "@posthog/ui/features/sessions/components/PlanStat import { QueuedMessagesDock } from "@posthog/ui/features/sessions/components/QueuedMessagesDock"; import { ReasoningLevelSelector } from "@posthog/ui/features/sessions/components/ReasoningLevelSelector"; import { RawLogsView } from "@posthog/ui/features/sessions/components/raw-logs/RawLogsView"; +import { SessionInitializingView } from "@posthog/ui/features/sessions/components/SessionInitializingView"; import { SessionResourcesBar } from "@posthog/ui/features/sessions/components/SessionResourcesBar"; import { SteerQueueToggle } from "@posthog/ui/features/sessions/components/SteerQueueToggle"; import { @@ -620,7 +620,10 @@ export function SessionView({ ) : isInitializing ? ( isCloud ? ( - + ) : pendingTaskPrompt?.promptText ? ( {runtime === "pi" && ( - + )} {runtime === "acp" && }