Refactor Foundry GitHub and sandbox flows

This commit is contained in:
Nathan Flurry 2026-03-12 10:51:33 -07:00
parent 4bccd5fc8d
commit ec8e816d0d
112 changed files with 4026 additions and 2715 deletions

View file

@ -3,7 +3,7 @@ import { describe, expect, it } from "vitest";
import type { HistoryEvent, RepoOverview } from "@sandbox-agent/foundry-shared";
import { createBackendClient } from "../../src/backend-client.js";
const RUN_FULL_E2E = process.env.HF_ENABLE_DAEMON_FULL_E2E === "1";
const DEFAULT_E2E_GITHUB_REPO = "rivet-dev/sandbox-agent-testing";
function requiredEnv(name: string): string {
const value = process.env[name]?.trim();
@ -106,10 +106,10 @@ async function ensureRemoteBranchExists(token: string, fullName: string, branchN
}
describe("e2e(client): full integration stack workflow", () => {
it.skipIf(!RUN_FULL_E2E)("adds repo, loads branch graph, and executes a stack restack action", { timeout: 8 * 60_000 }, async () => {
it("adds repo, loads branch graph, and executes a stack restack action", { timeout: 8 * 60_000 }, async () => {
const endpoint = process.env.HF_E2E_BACKEND_ENDPOINT?.trim() || "http://127.0.0.1:7741/api/rivet";
const workspaceId = process.env.HF_E2E_WORKSPACE?.trim() || "default";
const repoRemote = requiredEnv("HF_E2E_GITHUB_REPO");
const repoRemote = process.env.HF_E2E_GITHUB_REPO?.trim() || DEFAULT_E2E_GITHUB_REPO;
const githubToken = requiredEnv("GITHUB_TOKEN");
const { fullName } = parseGithubRepo(repoRemote);
const normalizedRepoRemote = `https://github.com/${fullName}.git`;

View file

@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
import type { TaskRecord, HistoryEvent } from "@sandbox-agent/foundry-shared";
import { createBackendClient } from "../../src/backend-client.js";
const RUN_E2E = process.env.HF_ENABLE_DAEMON_E2E === "1";
const DEFAULT_E2E_GITHUB_REPO = "rivet-dev/sandbox-agent-testing";
function requiredEnv(name: string): string {
const value = process.env[name]?.trim();
@ -143,10 +143,10 @@ async function githubApi(token: string, path: string, init?: RequestInit): Promi
}
describe("e2e: backend -> sandbox-agent -> git -> PR", () => {
it.skipIf(!RUN_E2E)("creates a task, waits for agent to implement, and opens a PR", { timeout: 15 * 60_000 }, async () => {
it("creates a task, waits for agent to implement, and opens a PR", { timeout: 15 * 60_000 }, async () => {
const endpoint = process.env.HF_E2E_BACKEND_ENDPOINT?.trim() || "http://127.0.0.1:7741/api/rivet";
const workspaceId = process.env.HF_E2E_WORKSPACE?.trim() || "default";
const repoRemote = requiredEnv("HF_E2E_GITHUB_REPO");
const repoRemote = process.env.HF_E2E_GITHUB_REPO?.trim() || DEFAULT_E2E_GITHUB_REPO;
const githubToken = requiredEnv("GITHUB_TOKEN");
const { fullName } = parseGithubRepo(repoRemote);

View file

@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest";
import type { TaskWorkbenchSnapshot, WorkbenchAgentTab, WorkbenchTask, WorkbenchModelId, WorkbenchTranscriptEvent } from "@sandbox-agent/foundry-shared";
import { createBackendClient } from "../../src/backend-client.js";
const RUN_WORKBENCH_E2E = process.env.HF_ENABLE_DAEMON_WORKBENCH_E2E === "1";
const DEFAULT_E2E_GITHUB_REPO = "rivet-dev/sandbox-agent-testing";
const execFileAsync = promisify(execFile);
function requiredEnv(name: string): string {
@ -144,10 +144,11 @@ function transcriptIncludesAgentText(transcript: WorkbenchTranscriptEvent[], exp
}
describe("e2e(client): workbench flows", () => {
it.skipIf(!RUN_WORKBENCH_E2E)("creates a task, adds sessions, exchanges messages, and manages workbench state", { timeout: 20 * 60_000 }, async () => {
it("creates a task, adds sessions, exchanges messages, and manages workbench state", { timeout: 20 * 60_000 }, async () => {
const endpoint = process.env.HF_E2E_BACKEND_ENDPOINT?.trim() || "http://127.0.0.1:7741/api/rivet";
const workspaceId = process.env.HF_E2E_WORKSPACE?.trim() || "default";
const repoRemote = requiredEnv("HF_E2E_GITHUB_REPO");
const repoRemote = process.env.HF_E2E_GITHUB_REPO?.trim() || DEFAULT_E2E_GITHUB_REPO;
requiredEnv("GITHUB_TOKEN");
const model = workbenchModelEnv("HF_E2E_MODEL", "gpt-4o");
const runId = `wb-${Date.now().toString(36)}`;
const expectedFile = `${runId}.txt`;

View file

@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
import type { TaskWorkbenchSnapshot, WorkbenchAgentTab, WorkbenchTask, WorkbenchModelId, WorkbenchTranscriptEvent } from "@sandbox-agent/foundry-shared";
import { createBackendClient } from "../../src/backend-client.js";
const RUN_WORKBENCH_LOAD_E2E = process.env.HF_ENABLE_DAEMON_WORKBENCH_LOAD_E2E === "1";
const DEFAULT_E2E_GITHUB_REPO = "rivet-dev/sandbox-agent-testing";
function requiredEnv(name: string): string {
const value = process.env[name]?.trim();
@ -174,10 +174,11 @@ async function measureWorkbenchSnapshot(
}
describe("e2e(client): workbench load", () => {
it.skipIf(!RUN_WORKBENCH_LOAD_E2E)("runs a simple sequential load profile against the real backend", { timeout: 30 * 60_000 }, async () => {
it("runs a simple sequential load profile against the real backend", { timeout: 30 * 60_000 }, async () => {
const endpoint = process.env.HF_E2E_BACKEND_ENDPOINT?.trim() || "http://127.0.0.1:7741/api/rivet";
const workspaceId = process.env.HF_E2E_WORKSPACE?.trim() || "default";
const repoRemote = requiredEnv("HF_E2E_GITHUB_REPO");
const repoRemote = process.env.HF_E2E_GITHUB_REPO?.trim() || DEFAULT_E2E_GITHUB_REPO;
requiredEnv("GITHUB_TOKEN");
const model = workbenchModelEnv("HF_E2E_MODEL", "gpt-4o");
const taskCount = intEnv("HF_LOAD_TASK_COUNT", 3);
const extraSessionCount = intEnv("HF_LOAD_EXTRA_SESSION_COUNT", 2);

View file

@ -1,21 +1,20 @@
import { describe, expect, it } from "vitest";
import { taskKey, taskStatusSyncKey, historyKey, projectBranchSyncKey, projectKey, projectPrSyncKey, sandboxInstanceKey, workspaceKey } from "../src/keys.js";
import { githubStateKey, historyKey, organizationKey, repositoryKey, sandboxInstanceKey, taskKey, taskStatusSyncKey } from "../src/keys.js";
describe("actor keys", () => {
it("prefixes every key with workspace namespace", () => {
it("prefixes every key with organization namespace", () => {
const keys = [
workspaceKey("default"),
projectKey("default", "repo"),
organizationKey("default"),
repositoryKey("default", "repo"),
githubStateKey("default"),
taskKey("default", "repo", "task"),
sandboxInstanceKey("default", "daytona", "sbx"),
historyKey("default", "repo"),
projectPrSyncKey("default", "repo"),
projectBranchSyncKey("default", "repo"),
taskStatusSyncKey("default", "repo", "task", "sandbox-1", "session-1"),
];
for (const key of keys) {
expect(key[0]).toBe("ws");
expect(key[0]).toBe("org");
expect(key[1]).toBe("default");
}
});