mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-17 05:00:20 +00:00
Fix E2B sandbox timeout comment, frontend stability, and create-flow improvements
- Add TEMPORARY comment on E2B timeoutMs with pointer to rivetkit sandbox resilience proposal for when autoPause lands - Fix React useEffect dependency stability in mock-layout and organization-dashboard to prevent infinite re-render loops - Fix terminal-pane ref handling - Improve create-flow service and tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
78cd38d826
commit
ee25a6c6a5
6 changed files with 106 additions and 42 deletions
|
|
@ -1317,11 +1317,14 @@ export function MockLayout({ organizationId, selectedTaskId, selectedSessionId }
|
|||
[organizationId],
|
||||
);
|
||||
const organizationState = useSubscription(subscriptionManager, "organization", { organizationId });
|
||||
const organizationRepos = organizationState.data?.repos ?? [];
|
||||
const taskSummaries = organizationState.data?.taskSummaries ?? [];
|
||||
const organizationReposData = organizationState.data?.repos;
|
||||
const taskSummariesData = organizationState.data?.taskSummaries;
|
||||
const openPullRequestsData = organizationState.data?.openPullRequests;
|
||||
const organizationRepos = organizationReposData ?? [];
|
||||
const taskSummaries = taskSummariesData ?? [];
|
||||
const selectedTaskSummary = useMemo(
|
||||
() => taskSummaries.find((task) => task.id === selectedTaskId) ?? taskSummaries[0] ?? null,
|
||||
[selectedTaskId, taskSummaries],
|
||||
[selectedTaskId, taskSummariesData],
|
||||
);
|
||||
const taskState = useSubscription(
|
||||
subscriptionManager,
|
||||
|
|
@ -1401,9 +1404,9 @@ export function MockLayout({ organizationId, selectedTaskId, selectedSessionId }
|
|||
summary.id === selectedTaskSummary?.id ? toTaskModel(summary, taskState.data, sessionCache) : toTaskModel(summary),
|
||||
);
|
||||
return hydratedTasks.sort((left, right) => right.updatedAtMs - left.updatedAtMs);
|
||||
}, [selectedTaskSummary, selectedSessionId, sessionState.data, taskState.data, taskSummaries, organizationId]);
|
||||
const openPullRequests = organizationState.data?.openPullRequests ?? [];
|
||||
const rawRepositories = useMemo(() => groupRepositories(organizationRepos, tasks, openPullRequests), [tasks, organizationRepos, openPullRequests]);
|
||||
}, [selectedTaskSummary, selectedSessionId, sessionState.data, taskState.data, taskSummariesData, organizationId]);
|
||||
const openPullRequests = openPullRequestsData ?? [];
|
||||
const rawRepositories = useMemo(() => groupRepositories(organizationRepos, tasks, openPullRequests), [tasks, organizationReposData, openPullRequestsData]);
|
||||
const appSnapshot = useMockAppSnapshot();
|
||||
const currentUser = activeMockUser(appSnapshot);
|
||||
const activeOrg = activeMockOrganization(appSnapshot);
|
||||
|
|
@ -1591,6 +1594,7 @@ export function MockLayout({ organizationId, selectedTaskId, selectedSessionId }
|
|||
}, [activeTask, lastAgentSessionIdByTask, selectedSessionId, syncRouteSession]);
|
||||
|
||||
useEffect(() => {
|
||||
const organizationRepos = organizationReposData ?? [];
|
||||
if (selectedNewTaskRepoId && organizationRepos.some((repo) => repo.id === selectedNewTaskRepoId)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1600,7 +1604,7 @@ export function MockLayout({ organizationId, selectedTaskId, selectedSessionId }
|
|||
if (fallbackRepoId !== selectedNewTaskRepoId) {
|
||||
setSelectedNewTaskRepoId(fallbackRepoId);
|
||||
}
|
||||
}, [activeTask?.repoId, selectedNewTaskRepoId, organizationRepos]);
|
||||
}, [activeTask?.repoId, selectedNewTaskRepoId, organizationReposData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeTask) {
|
||||
|
|
|
|||
|
|
@ -305,7 +305,8 @@ export function TerminalPane({ organizationId, taskId, isExpanded, onExpand, onC
|
|||
setProcessTabs([]);
|
||||
}, [taskId]);
|
||||
|
||||
const processes = processesState.data ?? [];
|
||||
const processesData = processesState.data;
|
||||
const processes = processesData ?? [];
|
||||
|
||||
const openTerminalTab = useCallback((process: SandboxProcessRecord) => {
|
||||
setProcessTabs((current) => {
|
||||
|
|
@ -361,7 +362,7 @@ export function TerminalPane({ organizationId, taskId, isExpanded, onExpand, onC
|
|||
const activeProcessTab = activeSessionId ? (processTabsById.get(activeSessionId) ?? null) : null;
|
||||
const activeTerminalProcess = useMemo(
|
||||
() => (activeProcessTab ? (processes.find((process) => process.id === activeProcessTab.processId) ?? null) : null),
|
||||
[activeProcessTab, processes],
|
||||
[activeProcessTab, processesData],
|
||||
);
|
||||
|
||||
const emptyBodyClassName = css({
|
||||
|
|
|
|||
|
|
@ -335,9 +335,11 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
const activeOrg = appState.data ? currentFoundryOrganization(appState.data) : null;
|
||||
|
||||
const organizationState = useSubscription(subscriptionManager, "organization", { organizationId });
|
||||
const repos = organizationState.data?.repos ?? [];
|
||||
const rows = organizationState.data?.taskSummaries ?? [];
|
||||
const selectedSummary = useMemo(() => rows.find((row) => row.id === selectedTaskId) ?? rows[0] ?? null, [rows, selectedTaskId]);
|
||||
const reposData = organizationState.data?.repos;
|
||||
const rowsData = organizationState.data?.taskSummaries;
|
||||
const repos = reposData ?? [];
|
||||
const rows = rowsData ?? [];
|
||||
const selectedSummary = useMemo(() => rows.find((row) => row.id === selectedTaskId) ?? rows[0] ?? null, [rowsData, selectedTaskId]);
|
||||
const taskState = useSubscription(
|
||||
subscriptionManager,
|
||||
"task",
|
||||
|
|
@ -363,6 +365,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
const repos = reposData ?? [];
|
||||
if (repoOverviewMode && selectedRepoId) {
|
||||
setCreateRepoId(selectedRepoId);
|
||||
return;
|
||||
|
|
@ -370,9 +373,11 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
if (!createRepoId && repos.length > 0) {
|
||||
setCreateRepoId(repos[0]!.id);
|
||||
}
|
||||
}, [createRepoId, repoOverviewMode, repos, selectedRepoId]);
|
||||
}, [createRepoId, repoOverviewMode, reposData, selectedRepoId]);
|
||||
|
||||
const repoGroups = useMemo(() => {
|
||||
const repos = reposData ?? [];
|
||||
const rows = rowsData ?? [];
|
||||
const byRepo = new Map<string, typeof rows>();
|
||||
for (const row of rows) {
|
||||
const bucket = byRepo.get(row.repoId);
|
||||
|
|
@ -400,7 +405,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
}
|
||||
return a.repoLabel.localeCompare(b.repoLabel);
|
||||
});
|
||||
}, [repos, rows]);
|
||||
}, [reposData, rowsData]);
|
||||
|
||||
const selectedForSession = repoOverviewMode ? null : (taskState.data ?? null);
|
||||
|
||||
|
|
@ -413,6 +418,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
}, [selectedForSession]);
|
||||
|
||||
useEffect(() => {
|
||||
const rows = rowsData ?? [];
|
||||
if (!repoOverviewMode && !selectedTaskId && rows.length > 0) {
|
||||
void navigate({
|
||||
to: "/organizations/$organizationId/tasks/$taskId",
|
||||
|
|
@ -424,14 +430,15 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
replace: true,
|
||||
});
|
||||
}
|
||||
}, [navigate, repoOverviewMode, rows, selectedTaskId, organizationId]);
|
||||
}, [navigate, repoOverviewMode, rowsData, selectedTaskId, organizationId]);
|
||||
|
||||
useEffect(() => {
|
||||
setActiveSessionId(null);
|
||||
setDraft("");
|
||||
}, [selectedForSession?.id]);
|
||||
|
||||
const sessionRows = selectedForSession?.sessionsSummary ?? [];
|
||||
const sessionRowsData = selectedForSession?.sessionsSummary;
|
||||
const sessionRows = sessionRowsData ?? [];
|
||||
const taskStatus = selectedForSession?.status ?? null;
|
||||
const taskStatusState = describeTaskState(taskStatus);
|
||||
const taskStateSummary = `${taskStatusState.title}. ${taskStatusState.detail}`;
|
||||
|
|
@ -450,7 +457,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
status: session.status,
|
||||
})),
|
||||
}),
|
||||
[activeSessionId, selectedForSession?.activeSessionId, sessionRows],
|
||||
[activeSessionId, selectedForSession?.activeSessionId, sessionRowsData],
|
||||
);
|
||||
const resolvedSessionId = sessionSelection.sessionId;
|
||||
const staleSessionId = sessionSelection.staleSessionId;
|
||||
|
|
@ -466,7 +473,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
}
|
||||
: null,
|
||||
);
|
||||
const selectedSessionSummary = useMemo(() => sessionRows.find((session) => session.id === resolvedSessionId) ?? null, [resolvedSessionId, sessionRows]);
|
||||
const selectedSessionSummary = useMemo(() => sessionRows.find((session) => session.id === resolvedSessionId) ?? null, [resolvedSessionId, sessionRowsData]);
|
||||
const isPendingProvision = selectedSessionSummary?.status === "pending_provision";
|
||||
const isPendingSessionCreate = selectedSessionSummary?.status === "pending_session_create";
|
||||
const isSessionError = selectedSessionSummary?.status === "error";
|
||||
|
|
@ -523,7 +530,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
activeSandboxId: selectedForSession?.id === task.id ? selectedForSession.activeSandboxId : null,
|
||||
})),
|
||||
}),
|
||||
[repos, rows, selectedForSession, organizationId],
|
||||
[reposData, rowsData, selectedForSession, organizationId],
|
||||
);
|
||||
|
||||
const startSessionFromTask = async (): Promise<{ id: string; status: "running" | "idle" | "error" }> => {
|
||||
|
|
@ -631,7 +638,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
setCreateTaskOpen(true);
|
||||
};
|
||||
|
||||
const repoOptions = useMemo(() => repos.map((repo) => createOption({ id: repo.id, label: repo.label })), [repos]);
|
||||
const repoOptions = useMemo(() => repos.map((repo) => createOption({ id: repo.id, label: repo.label })), [reposData]);
|
||||
const selectedRepoOption = repoOptions.find((option) => option.id === createRepoId) ?? null;
|
||||
const selectedFilterOption = useMemo(
|
||||
() => createOption(FILTER_OPTIONS.find((option) => option.id === overviewFilter) ?? FILTER_OPTIONS[0]!),
|
||||
|
|
@ -639,7 +646,7 @@ export function OrganizationDashboard({ organizationId, selectedTaskId, selected
|
|||
);
|
||||
const sessionOptions = useMemo(
|
||||
() => sessionRows.map((session) => createOption({ id: session.id, label: `${session.sessionName} (${session.status})` })),
|
||||
[sessionRows],
|
||||
[sessionRowsData],
|
||||
);
|
||||
const selectedSessionOption = sessionOptions.find((option) => option.id === resolvedSessionId) ?? null;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue