Add star repo onboarding flow

This commit is contained in:
Nathan Flurry 2026-03-10 23:46:01 -07:00
parent d2346bafb3
commit 1a6ae37e10
9 changed files with 330 additions and 89 deletions

View file

@ -25,6 +25,8 @@ import type {
RepoStackActionInput,
RepoStackActionResult,
RepoRecord,
StarSandboxAgentRepoInput,
StarSandboxAgentRepoResult,
SwitchResult,
WorkspaceUseInput,
} from "@openhandoff/shared";
@ -59,6 +61,7 @@ interface RepoOverviewInput {
}
const WORKSPACE_QUEUE_NAMES = ["workspace.command.addRepo", "workspace.command.createHandoff", "workspace.command.refreshProviderProfiles"] as const;
const SANDBOX_AGENT_REPO = "rivet-dev/sandbox-agent";
type WorkspaceQueueName = (typeof WORKSPACE_QUEUE_NAMES)[number];
@ -415,6 +418,16 @@ export const workspaceActions = {
);
},
async starSandboxAgentRepo(c: any, input: StarSandboxAgentRepoInput): Promise<StarSandboxAgentRepoResult> {
assertWorkspace(c, input.workspaceId);
const { driver } = getActorRuntimeContext();
await driver.github.starRepository(SANDBOX_AGENT_REPO);
return {
repo: SANDBOX_AGENT_REPO,
starredAt: Date.now(),
};
},
async getWorkbench(c: any, input: WorkspaceUseInput): Promise<HandoffWorkbenchSnapshot> {
assertWorkspace(c, input.workspaceId);
return await buildWorkbenchSnapshot(c);

View file

@ -24,7 +24,7 @@ import {
gitSpiceSyncRepo,
gitSpiceTrackBranch,
} from "./integrations/git-spice/index.js";
import { listPullRequests, createPr } from "./integrations/github/index.js";
import { listPullRequests, createPr, starRepository } from "./integrations/github/index.js";
import { SandboxAgentClient } from "./integrations/sandbox-agent/client.js";
import { DaytonaClient } from "./integrations/daytona/client.js";
@ -59,6 +59,7 @@ export interface StackDriver {
export interface GithubDriver {
listPullRequests(repoPath: string): Promise<PullRequestSnapshot[]>;
createPr(repoPath: string, headBranch: string, title: string, body?: string): Promise<{ number: number; url: string }>;
starRepository(repoFullName: string): Promise<void>;
}
export interface SandboxAgentClientLike {
@ -131,6 +132,7 @@ export function createDefaultDriver(): BackendDriver {
github: {
listPullRequests,
createPr,
starRepository,
},
sandboxAgent: {
createClient: (opts) => {

View file

@ -167,6 +167,18 @@ export async function createPr(repoPath: string, headBranch: string, title: stri
return { number, url };
}
export async function starRepository(repoFullName: string): Promise<void> {
try {
await execFileAsync("gh", ["api", "--method", "PUT", `user/starred/${repoFullName}`], {
maxBuffer: 1024 * 1024,
});
} catch (error) {
const message =
error instanceof Error ? error.message : `Failed to star GitHub repository ${repoFullName}. Ensure GitHub auth is configured for the backend.`;
throw new Error(message);
}
}
export async function getAllowedMergeMethod(repoPath: string): Promise<"squash" | "rebase" | "merge"> {
try {
// Get the repo owner/name from gh

View file

@ -58,6 +58,7 @@ export function createTestGithubDriver(overrides?: Partial<GithubDriver>): Githu
number: 1,
url: `https://github.com/test/repo/pull/1`,
}),
starRepository: async () => {},
...overrides,
};
}

View file

@ -0,0 +1,39 @@
// @ts-nocheck
import { describe, expect, it } from "vitest";
import { setupTest } from "rivetkit/test";
import { workspaceKey } from "../src/actors/keys.js";
import { registry } from "../src/actors/index.js";
import { createTestDriver } from "./helpers/test-driver.js";
import { createTestRuntimeContext } from "./helpers/test-context.js";
const runActorIntegration = process.env.HF_ENABLE_ACTOR_INTEGRATION_TESTS === "1";
describe("workspace star sandbox agent repo", () => {
it.skipIf(!runActorIntegration)("stars the sandbox agent repo through the github driver", async (t) => {
const calls: string[] = [];
const testDriver = createTestDriver({
github: {
listPullRequests: async () => [],
createPr: async () => ({
number: 1,
url: "https://github.com/test/repo/pull/1",
}),
starRepository: async (repoFullName) => {
calls.push(repoFullName);
},
},
});
createTestRuntimeContext(testDriver);
const { client } = await setupTest(t, registry);
const ws = await client.workspace.getOrCreate(workspaceKey("alpha"), {
createWithInput: "alpha",
});
const result = await ws.starSandboxAgentRepo({ workspaceId: "alpha" });
expect(calls).toEqual(["rivet-dev/sandbox-agent"]);
expect(result.repo).toBe("rivet-dev/sandbox-agent");
expect(typeof result.starredAt).toBe("number");
});
});