Ctrl K
ComunidadGuías…

tests/e2e/control-sandbox-lifecycle.spec.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { expect, test } from "@playwright/test";
import type { UIMessageChunk } from "ai";
import {
  appendSandboxTaskLifecycleFooter,
  createSandboxTaskLifecycle,
} from "@/lib/agents/orchestrator/sandbox-task-lifecycle";
import { enableScopedE2EAuth, scopedPath } from "./helpers/auth";
import {
  mockBaseChrome,
  mockControlSessionBootstrap,
} from "./helpers/automation-control-plane-fixtures";

for (const stopResult of [true, "activity_unknown"] as const) {
  const outcome =
    stopResult === true
      ? "paused compute without routine chatter"
      : "an unavailable activity check";
  test(`completed task cleanup reports ${outcome}`, async ({ page }) => {
    await enableScopedE2EAuth(page);
    await mockBaseChrome(page);
    await mockControlSessionBootstrap(page);
    const binding = {
      sandboxId: "sandbox-1" as string | null,
      status: "running" as "running" | "pending" | "unavailable",
    };
    await page.route("**/api/control/chat", async (route) => {
      const lifecycle = createSandboxTaskLifecycle({
        userId: "user-1",
        aiCallId: "current-call",
        userText: "Run the checks",
        binding,
        deps: {
          loadState: async () => ({
            status: "running",
            previewUrl: null,
          }),
          stop: async () => stopResult,
        },
      });
      const toolCall = {
        toolName: "run_command",
        input: { command: "pnpm typecheck" },
      };
      lifecycle.onToolStart({ toolCall });
      lifecycle.onToolFinish({
        toolCall,
        output: { sandboxId: "sandbox-1", exitCode: 0 },
        success: true,
      });
      const source = new ReadableStream<UIMessageChunk>({
        start(controller) {
          for (const chunk of [
            { type: "start", messageId: "reply" },
            { type: "text-start", id: "text" },
            { type: "text-delta", id: "text", delta: "Typecheck passed." },
            { type: "text-end", id: "text" },
            { type: "finish", finishReason: "stop" },
          ] as UIMessageChunk[])
            controller.enqueue(chunk);
          controller.close();
        },
      });
      const reader = appendSandboxTaskLifecycleFooter(source, {
        footer: lifecycle.footer,
        textPartId: "lifecycle",
      }).getReader();
      const chunks: UIMessageChunk[] = [];
      for (;;) {
        const { done, value } = await reader.read();
        if (done) break;
        chunks.push(value);
      }
      await route.fulfill({
        headers: {
          "content-type": "text/event-stream",
          "x-vercel-ai-ui-message-stream": "v1",
        },
        body:
          chunks.map((chunk) => `data: ${JSON.stringify(chunk)}\n\n`).join("") +
          "data: [DONE]\n\n",
      });
    });
    await page.goto(scopedPath("control"));
    await page
      .getByPlaceholder("Ask anything or run a command...")
      .fill("Run the checks");
    await page.getByRole("button", { name: "Start mission" }).click();
    const transcript = page.getByRole("log", { name: "Conversation" });
    await expect(transcript).toContainText("Typecheck passed.");
    await expect(transcript).not.toContainText("Compute:");
    expect(binding.status).toBe(
      stopResult === true ? "unavailable" : "running"
    );
    if (stopResult === "activity_unknown") {
      await expect(transcript).toContainText(
        "Compute was left running because active work could not be checked."
      );
      await expect(transcript).not.toContainText("Could not confirm");
    }
  });
}