This commit is contained in:
Nathan Flurry 2026-03-16 00:41:53 -07:00
parent aa332307e5
commit b372383cfd
47 changed files with 1845 additions and 1212 deletions

View file

@ -470,9 +470,7 @@ export const DevPanel = memo(function DevPanel({ organizationId, snapshot, organ
/>
<span className={css({ color: t.textPrimary, flex: 1 })}>Sync</span>
<span className={`${mono} ${css({ color: syncStatusColor(liveGithub.syncStatus, t) })}`}>{liveGithub.syncStatus}</span>
{liveGithub.lastSyncAt != null && (
<span className={`${mono} ${css({ color: t.textTertiary })}`}>{timeAgo(liveGithub.lastSyncAt)}</span>
)}
{liveGithub.lastSyncAt != null && <span className={`${mono} ${css({ color: t.textTertiary })}`}>{timeAgo(liveGithub.lastSyncAt)}</span>}
</div>
<div className={css({ display: "flex", alignItems: "center", gap: "6px" })}>
<span
@ -496,17 +494,14 @@ export const DevPanel = memo(function DevPanel({ organizationId, snapshot, organ
<div className={css({ display: "flex", gap: "10px", marginTop: "2px" })}>
<Stat label="imported" value={liveGithub.importedRepoCount} t={t} css={css} />
<Stat label="catalog" value={organization?.repoCatalog.length ?? repos.length} t={t} css={css} />
<Stat label="target" value={liveGithub.totalRepositoryCount} t={t} css={css} />
<Stat label="target" value={liveGithub.totalRepositoryCount ?? 0} t={t} css={css} />
</div>
{liveGithub.connectedAccount && (
<div className={`${mono} ${css({ color: t.textMuted, marginTop: "1px" })}`}>@{liveGithub.connectedAccount}</div>
)}
{liveGithub.lastSyncLabel && (
<div className={`${mono} ${css({ color: t.textMuted })}`}>last sync: {liveGithub.lastSyncLabel}</div>
)}
{liveGithub.connectedAccount && <div className={`${mono} ${css({ color: t.textMuted, marginTop: "1px" })}`}>@{liveGithub.connectedAccount}</div>}
{liveGithub.lastSyncLabel && <div className={`${mono} ${css({ color: t.textMuted })}`}>last sync: {liveGithub.lastSyncLabel}</div>}
{liveGithub.syncPhase && (
<div className={`${mono} ${css({ color: t.textTertiary })}`}>
phase: {liveGithub.syncPhase.replace(/^syncing_/, "").replace(/_/g, " ")} ({liveGithub.processedRepositoryCount}/{liveGithub.totalRepositoryCount})
phase: {liveGithub.syncPhase.replace(/^syncing_/, "").replace(/_/g, " ")} ({liveGithub.processedRepositoryCount}/
{liveGithub.totalRepositoryCount})
</div>
)}
</div>

View file

@ -80,7 +80,10 @@ function sanitizeActiveSessionId(task: Task, sessionId: string | null | undefine
return openDiffs.length > 0 ? diffTabId(openDiffs[openDiffs.length - 1]!) : lastAgentSessionId;
}
type GithubStatusView = Pick<FoundryOrganization["github"], "connectedAccount" | "installationStatus" | "syncStatus" | "importedRepoCount" | "lastSyncLabel"> & {
type GithubStatusView = Pick<
FoundryOrganization["github"],
"connectedAccount" | "installationStatus" | "syncStatus" | "importedRepoCount" | "lastSyncLabel"
> & {
syncPhase?: string | null;
processedRepositoryCount?: number;
totalRepositoryCount?: number;
@ -1912,7 +1915,7 @@ export function MockLayout({ organizationId, selectedTaskId, selectedSessionId }
<h2 style={{ margin: 0, fontSize: "20px", fontWeight: 600 }}>Syncing with GitHub</h2>
<p style={{ margin: 0, opacity: 0.75 }}>
{liveGithub.lastSyncLabel || `Importing repos from @${liveGithub.connectedAccount || "GitHub"}...`}
{liveGithub.totalRepositoryCount > 0 && (
{(liveGithub.totalRepositoryCount ?? 0) > 0 && (
<>
{" "}
{liveGithub.syncPhase === "syncing_repositories"

View file

@ -530,8 +530,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
if (!selectedForSession || !activeSandbox?.sandboxId) {
throw new Error("No sandbox is available for this task");
}
const preferredAgent =
selectedSessionSummary?.agent === "Claude" ? "claude" : selectedSessionSummary?.agent === "Codex" ? "codex" : undefined;
const preferredAgent = selectedSessionSummary?.agent === "Claude" ? "claude" : selectedSessionSummary?.agent === "Codex" ? "codex" : undefined;
return backendClient.createSandboxSession({
organizationId,
sandboxProviderId: activeSandbox.sandboxProviderId,
@ -1114,7 +1113,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
{selectedForSession ? (
<HeaderStatusPill
status={deriveHeaderStatus(
taskRuntimeStatus ?? selectedForSession.status,
taskStatus ?? selectedForSession.status,
selectedSessionSummary?.status ?? null,
selectedSessionSummary?.errorMessage ?? null,
Boolean(activeSandbox?.sandboxId),
@ -1242,7 +1241,9 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
<ParagraphSmall marginTop="0" marginBottom="0" color="contentSecondary">
{shouldUseTaskStateEmptyState
? taskStateSummary
: (isPendingProvision ? "The task is still provisioning." : "The session is being created.")}
: isPendingProvision
? "The task is still provisioning."
: "The session is being created."}
</ParagraphSmall>
</div>
) : null}
@ -1456,7 +1457,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
gap: theme.sizing.scale300,
})}
>
<MetaRow label="State" value={taskRuntimeStatus ?? "-"} mono />
<MetaRow label="State" value={taskStatus ?? "-"} mono />
<MetaRow label="State detail" value={taskStatusState.detail} />
<MetaRow label="Task" value={selectedForSession.id} mono />
<MetaRow label="Sandbox" value={selectedForSession.activeSandboxId ?? "-"} mono />
@ -1501,7 +1502,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
</div>
</section>
{taskRuntimeStatus === "error" ? (
{taskStatus === "error" ? (
<div
className={css({
padding: "12px",

View file

@ -53,6 +53,7 @@ const remoteAppClient: FoundryAppClient = {
await backendClient.signInWithGithub();
},
async signOut(): Promise<void> {
window.localStorage.removeItem(REMOTE_APP_SESSION_STORAGE_KEY);
await backendClient.signOutApp();
},
async skipStarterRepo(): Promise<void> {
@ -100,6 +101,14 @@ export function useMockAppSnapshot(): FoundryAppSnapshot {
const app = useSubscription(subscriptionManager, "app", {});
if (app.status !== "loading") {
firstSnapshotDelivered = true;
// Persist session sentinel so isAppSnapshotBootstrapping can show a loading
// screen instead of flashing /signin on the next page load / HMR reload.
const snapshot = app.data ?? EMPTY_APP_SNAPSHOT;
if (snapshot.auth.status === "signed_in") {
window.localStorage.setItem(REMOTE_APP_SESSION_STORAGE_KEY, "1");
} else {
window.localStorage.removeItem(REMOTE_APP_SESSION_STORAGE_KEY);
}
}
return app.data ?? EMPTY_APP_SNAPSHOT;
}