History

Retry desktop project bootstrap when list is transiently empty

Cursor Agent committed 9 months ago

Commit cec360e1 parent 5cda7712 files · +35 −2Browse files

Unified · Split

2 files
  1. apps/web/src/App.tsx +12 −2
  2. scripts/desktop-perf-trace.mjs +23 −0
apps/web/src/App.tsx+12−2
@@ -124,7 +124,7 @@ function AutoProjectBootstrap() { · 123 unmodified lines
124124
125125 function DesktopProjectBootstrap() {
126126 const api = useNativeApi();
127− const { dispatch } = useStore();
127+ const { state, dispatch } = useStore();
128128 const bootstrappedRef = useRef(false);
129129
130130 useEffect(() => {
@@ -138,6 +138,16 @@ function DesktopProjectBootstrap() { · 7 unmodified lines
138138 try {
139139 const projects = await api.projects.list();
140140 if (disposed) return;
141+ if (projects.length === 0 && (state.projects.length > 0 || state.threads.length > 0)) {
142+ // Avoid wiping hydrated renderer state if the initial projects.list races
143+ // backend startup and transiently returns no projects.
144+ retryTimer = setTimeout(() => {
145+ retryTimer = null;
146+ void attemptBootstrap();
147+ }, retryDelayMs);
148+ retryDelayMs = Math.min(retryDelayMs * 2, 5_000);
149+ return;
150+ }
141151 dispatch({
142152 type: "SYNC_PROJECTS",
143153 projects: projects.map((project) => ({
@@ -167,7 +177,7 @@ function DesktopProjectBootstrap() { · 23 unmodified lines
167177 clearTimeout(retryTimer);
168178 }
169179 };
170− }, [api, dispatch]);
180+ }, [api, dispatch, state.projects.length, state.threads.length]);
171181
172182 return null;
173183 }
scripts/desktop-perf-trace.mjs+23−0
@@ -668,6 +668,29 @@ async function main() { · 667 unmodified lines
668668 );
669669 }
670670
671+ const interactionChecks = [];
672+ const threadClicks = Number(donePayload.interactions?.threadClicks ?? 0);
673+ const typedChars = Number(donePayload.interactions?.typedChars ?? 0);
674+ const terminalOpened = donePayload.interactions?.terminal?.openedByShortcut === true;
675+ const terminalCommandTouched = donePayload.interactions?.terminal?.commandFileTouched === true;
676+ if (threadClicks <= 0) {
677+ interactionChecks.push("thread clicks");
678+ }
679+ if (typedChars <= 0) {
680+ interactionChecks.push("typed chars");
681+ }
682+ if (!terminalOpened) {
683+ interactionChecks.push("terminal shortcut open");
684+ }
685+ if (!terminalCommandTouched) {
686+ interactionChecks.push("terminal command execution");
687+ }
688+ if (interactionChecks.length > 0) {
689+ throw new Error(
690+ `Desktop perf automation completed without required scripted interactions: ${interactionChecks.join(", ")}`,
691+ );
692+ }
693+
671694 const summary = summarizeTrace(tracePath);
672695 const markdown = createMarkdownSummary({
673696 tracePath,