Rename Foundry handoffs to tasks (#239)

* Restore foundry onboarding stack

* Consolidate foundry rename

* Create foundry tasks without prompts

* Rename Foundry handoffs to tasks
This commit is contained in:
Nathan Flurry 2026-03-11 13:23:54 -07:00 committed by GitHub
parent d30cc0bcc8
commit d75e8c31d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
281 changed files with 9242 additions and 4356 deletions

View file

@ -0,0 +1,67 @@
import type {
FoundryAppSnapshot,
FoundryBillingPlanId,
FoundryOrganization,
FoundryUser,
UpdateFoundryOrganizationProfileInput,
} from "@sandbox-agent/foundry-shared";
import type { BackendClient } from "./backend-client.js";
import { getMockFoundryAppClient } from "./mock-app.js";
import { createRemoteFoundryAppClient } from "./remote/app-client.js";
export interface FoundryAppClient {
getSnapshot(): FoundryAppSnapshot;
subscribe(listener: () => void): () => void;
signInWithGithub(userId?: string): Promise<void>;
signOut(): Promise<void>;
skipStarterRepo(): Promise<void>;
starStarterRepo(organizationId: string): Promise<void>;
selectOrganization(organizationId: string): Promise<void>;
updateOrganizationProfile(input: UpdateFoundryOrganizationProfileInput): Promise<void>;
triggerGithubSync(organizationId: string): Promise<void>;
completeHostedCheckout(organizationId: string, planId: FoundryBillingPlanId): Promise<void>;
openBillingPortal(organizationId: string): Promise<void>;
cancelScheduledRenewal(organizationId: string): Promise<void>;
resumeSubscription(organizationId: string): Promise<void>;
reconnectGithub(organizationId: string): Promise<void>;
recordSeatUsage(workspaceId: string): Promise<void>;
}
export interface CreateFoundryAppClientOptions {
mode: "mock" | "remote";
backend?: BackendClient;
}
export function createFoundryAppClient(options: CreateFoundryAppClientOptions): FoundryAppClient {
if (options.mode === "mock") {
return getMockFoundryAppClient() as unknown as FoundryAppClient;
}
if (!options.backend) {
throw new Error("Remote app client requires a backend client");
}
return createRemoteFoundryAppClient({ backend: options.backend });
}
export function currentFoundryUser(snapshot: FoundryAppSnapshot): FoundryUser | null {
if (!snapshot.auth.currentUserId) {
return null;
}
return snapshot.users.find((candidate) => candidate.id === snapshot.auth.currentUserId) ?? null;
}
export function currentFoundryOrganization(snapshot: FoundryAppSnapshot): FoundryOrganization | null {
if (!snapshot.activeOrganizationId) {
return null;
}
return snapshot.organizations.find((candidate) => candidate.id === snapshot.activeOrganizationId) ?? null;
}
export function eligibleFoundryOrganizations(snapshot: FoundryAppSnapshot): FoundryOrganization[] {
const user = currentFoundryUser(snapshot);
if (!user) {
return [];
}
const eligible = new Set(user.eligibleOrganizationIds);
return snapshot.organizations.filter((organization) => eligible.has(organization.id));
}