Skip to content

Conversation

@RayFernando1337
Copy link
Contributor

@RayFernando1337 RayFernando1337 commented Jan 1, 2026

API requests were being made before initApiKey() completed, causing 401 Unauthorized errors on app startup in Electron mode.

Changes:

  • Add waitForApiKeyInit() to track and await API key initialization
  • Make HTTP methods (get/post/put/delete) wait for auth before requests
  • Defer WebSocket connection until API key is ready
  • Add explicit auth wait in useSettingsMigration hook

Fixes race condition introduced in PR #321


Fix Report: Auth Race Condition (401 Errors on Startup)

Summary

Fixed the race condition where API requests were made before initApiKey() completed, causing 401 errors on Electron app startup.

Root Cause

In PR #321 (protect-api-with-api-key), the authentication system was hardened to require API keys for all requests. However, initApiKey() was called asynchronously in a useEffect hook, while other hooks (useSettingsMigration, useRunningAgents) immediately created HttpApiClient instances and made API requests before the API key was fetched from Electron's main process.

Timeline of the bug:

  1. App starts, React renders components
  2. useSettingsMigration and other hooks call getHttpApiClient()
  3. HttpApiClient constructor calls connectWebSocket() which needs auth
  4. API requests fire with getApiKey() returning null
  5. Server returns 401 Unauthorized
  6. Later, initApiKey() in __root.tsx useEffect finally completes
  7. [HTTP Client] Using API key from Electron appears in logs - too late!

Changes Made

1. apps/ui/src/lib/http-api-client.ts

Added apiKeyInitPromise to track initialization:

let apiKeyInitPromise: Promise<void> | null = null;

Added waitForApiKeyInit() helper function:

export const waitForApiKeyInit = (): Promise<void> => {
  if (apiKeyInitialized) return Promise.resolve();
  if (apiKeyInitPromise) return apiKeyInitPromise;
  return initApiKey();
};

Modified initApiKey() to return a trackable promise:

  • Stores the initialization promise so concurrent calls wait for the same initialization
  • Prevents duplicate initialization attempts

Modified HttpApiClient constructor to wait for auth:

constructor() {
  this.serverUrl = getServerUrl();
  // Wait for API key initialization before connecting WebSocket
  waitForApiKeyInit().then(() => {
    this.connectWebSocket();
  });
}

Modified HTTP methods (get, post, put, httpDelete) to wait for auth:

private async get<T>(endpoint: string): Promise<T> {
  // Ensure API key is initialized before making request
  await waitForApiKeyInit();
  // ... rest of method
}

2. apps/ui/src/hooks/use-settings-migration.ts

Added wait for auth before API calls:

import { getHttpApiClient, waitForApiKeyInit } from '@/lib/http-api-client';

// In checkAndMigrate():
await waitForApiKeyInit();
const api = getHttpApiClient();

Testing

After the fix:

  • [HTTP Client] Using API key from Electron appears BEFORE any API requests
  • No more 401 errors on startup
  • WebSocket connects successfully
  • Settings migration works correctly

Files Changed

  1. apps/ui/src/lib/http-api-client.ts - Core fix for auth initialization
  2. apps/ui/src/hooks/use-settings-migration.ts - Added explicit wait for auth

Notes

  • The fix uses a promise-based approach that allows all API methods to wait for auth
  • This is backwards-compatible - web mode (cookie-based auth) still works
  • The waitForApiKeyInit() function returns immediately if already initialized, so there's no performance penalty after first load
  • Consider adding similar waits to any other hooks that make early API calls

Related

Summary by CodeRabbit

  • Bug Fixes
    • Fixed 401 authentication errors during startup by ensuring API key initialization completes before HTTP requests and real-time connections.
    • Improved startup behavior to avoid repeated initialization attempts and to fall back to cookie-based authentication with a warning when needed, while still attempting real-time connections.

✏️ Tip: You can customize this high-level summary in your review settings.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @RayFernando1337, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical race condition that caused 401 Unauthorized errors during the Electron application's startup. By implementing a robust promise-based mechanism to track and await API key initialization, all API-dependent operations, including HTTP requests and WebSocket connections, are now properly synchronized. This ensures that authentication is fully established before any network calls are made, significantly improving the stability and reliability of the application in Electron mode.

Highlights

  • Race Condition Fix: Resolved a race condition in Electron mode where API requests were made before the API key was initialized, leading to 401 Unauthorized errors on application startup.
  • API Key Initialization Tracking: Introduced apiKeyInitPromise and waitForApiKeyInit() to track and await the completion of API key initialization, ensuring all dependent operations wait for authentication readiness.
  • Synchronized HTTP Requests: Modified all HTTP methods (get, post, put, delete) in HttpApiClient to explicitly await waitForApiKeyInit() before dispatching requests.
  • Deferred WebSocket Connection: The HttpApiClient constructor now defers the WebSocket connection until the API key has been successfully initialized.
  • Settings Migration Hook Update: The useSettingsMigration hook now includes an explicit await waitForApiKeyInit() call before making any API requests, preventing early unauthorized calls.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Jan 1, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds a coordination mechanism to ensure API key initialization completes before creating HttpApiClient, opening WebSocket connections, or issuing HTTP requests in Electron startup flows, preventing premature 401 responses.

Changes

Cohort / File(s) Summary
API key init & HttpApiClient
apps/ui/src/lib/http-api-client.ts
Added waitForApiKeyInit(): Promise<void> and apiKeyInitPromise to coordinate one-time API key initialization; initApiKey() now returns/shared promise. Updated HttpApiClient to await initialization in constructor (WebSocket startup) and in HTTP methods (post, get, put, httpDelete). Added fallback/logging on Electron API key fetch failure.
Settings migration hook
apps/ui/src/hooks/use-settings-migration.ts
Imported and awaited waitForApiKeyInit() in the Electron startup migration path before creating the HTTP client and making API calls to avoid startup 401s.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Hook as Settings Hook
  participant Client as HttpApiClient
  participant Init as API Key Init
  participant Server as Backend (HTTP/WebSocket)

  rect rgba(200,230,255,0.3)
  Hook->>Init: call waitForApiKeyInit()
  note right of Init: ensures single init promise
  Init-->>Hook: resolves when API key available
  end

  rect rgba(220,255,220,0.3)
  Hook->>Client: instantiate HttpApiClient
  Client->>Init: await waitForApiKeyInit()
  Init-->>Client: resolved (or fallback)
  Client->>Server: open WebSocket / send HTTP requests
  Server-->>Client: responses
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 I waited for keys beneath the moonlit byte,

No more 401s to give us a fright.
WebSocket and requests now start on cue,
Hops of relief — a clean startup view!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing a race condition that causes 401 errors on Electron startup by ensuring API key initialization before requests.
✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a race condition during application startup by introducing a promise-based mechanism to ensure the API key is initialized before any API requests are made. The changes are well-structured and applied consistently across the HTTP client and relevant hooks. I've identified a critical issue in the implementation of the initialization logic that could lead to a persistent failure state, and a medium-severity issue regarding unhandled promise rejections for improved robustness. Once these are addressed, the fix should be solid.

Comment on lines 101 to 122
apiKeyInitPromise = (async () => {
apiKeyInitialized = true;

// Only Electron mode uses API key header auth
if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
try {
cachedApiKey = await window.electronAPI.getApiKey();
if (cachedApiKey) {
console.log('[HTTP Client] Using API key from Electron');
return;
}
} catch (error) {
console.warn('[HTTP Client] Failed to get API key from Electron:', error);
}
} catch (error) {
console.warn('[HTTP Client] Failed to get API key from Electron:', error);
}
}

// In web mode, authentication is handled via HTTP-only cookies
console.log('[HTTP Client] Web mode - using cookie-based authentication');
// In web mode, authentication is handled via HTTP-only cookies
console.log('[HTTP Client] Web mode - using cookie-based authentication');
})();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The apiKeyInitialized flag is set to true at the beginning of the async operation. If window.electronAPI.getApiKey() fails or returns a falsy value, apiKeyInitialized will still be true. Subsequent calls to waitForApiKeyInit() will then resolve immediately without a valid API key, leading to persistent 401 errors for all API requests. The flag should only be set after the initialization attempt is complete. Using a finally block is the most robust way to ensure it's always set upon completion, regardless of success or failure.

  apiKeyInitPromise = (async () => {
    try {
      // Only Electron mode uses API key header auth
      if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
        cachedApiKey = await window.electronAPI.getApiKey();
        if (cachedApiKey) {
          console.log('[HTTP Client] Using API key from Electron');
          return;
        }
      }
      // In web mode, or if Electron API key fetch fails/returns null
      console.log('[HTTP Client] Web mode - using cookie-based authentication');
    } catch (error) {
      console.warn('[HTTP Client] Failed to get API key from Electron:', error);
    } finally {
      apiKeyInitialized = true;
    }
  })();

Comment on lines 323 to 325
waitForApiKeyInit().then(() => {
this.connectWebSocket();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This promise chain is missing a .catch() handler. While the current implementation of waitForApiKeyInit() may not reject, it's a good practice for robustness and future maintainability to handle potential promise rejections. This prevents unhandledrejection errors if the underlying logic changes and helps in debugging if initialization fails unexpectedly.

    waitForApiKeyInit()
      .then(() => {
        this.connectWebSocket();
      })
      .catch((error) => {
        console.error(
          '[HTTP Client] API key initialization failed, WebSocket connection aborted:',
          error
        );
      });

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/ui/src/lib/http-api-client.ts (1)

56-122: Recommended: Add timeout to prevent indefinite blocking.

The current implementation has no timeout mechanism for API key initialization. If the Electron bridge hangs or is unresponsive, all HTTP requests and WebSocket connections will block indefinitely.

🔎 Suggested timeout wrapper
// Add a helper with timeout
const withTimeout = <T>(promise: Promise<T>, ms: number): Promise<T> => {
  return Promise.race([
    promise,
    new Promise<T>((_, reject) =>
      setTimeout(() => reject(new Error('API key initialization timeout')), ms)
    ),
  ]);
};

export const waitForApiKeyInit = (): Promise<void> => {
  if (apiKeyInitPromise) return apiKeyInitPromise;
  if (apiKeyInitialized) return Promise.resolve();
  // Add 5-second timeout to prevent indefinite blocking
  return withTimeout(initApiKey(), 5000).catch((error) => {
    console.error('[HTTP Client] API key initialization failed:', error);
    // Fall back to web mode on timeout
    apiKeyInitialized = true;
  });
};

This ensures the app remains responsive even if Electron bridge initialization fails.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 847a8ff and 2f6c397.

📒 Files selected for processing (2)
  • apps/ui/src/hooks/use-settings-migration.ts
  • apps/ui/src/lib/http-api-client.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/hooks/use-settings-migration.ts
  • apps/ui/src/lib/http-api-client.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/hooks/use-settings-migration.ts
  • apps/ui/src/lib/http-api-client.ts
🧬 Code graph analysis (1)
apps/ui/src/hooks/use-settings-migration.ts (1)
apps/ui/src/lib/http-api-client.ts (1)
  • waitForApiKeyInit (60-65)
🔇 Additional comments (5)
apps/ui/src/hooks/use-settings-migration.ts (2)

21-21: LGTM!

The import addition is clean and follows the existing import patterns.


102-104: LGTM - Race condition fix implemented correctly.

The explicit await on waitForApiKeyInit() ensures the API key is initialized before any HTTP requests are made, preventing 401 errors during startup. The comment clearly explains the rationale.

apps/ui/src/lib/http-api-client.ts (3)

47-47: LGTM - Promise caching mechanism.

The module-level promise variable enables coordination between multiple callers, ensuring only one initialization occurs.


319-326: LGTM - WebSocket connection deferred correctly.

The constructor properly defers WebSocket connection until API key initialization completes, preventing 401 errors. The .then() pattern is appropriate since constructors cannot be async.

Note: This depends on the waitForApiKeyInit() fix (lines 56-65) to function correctly.


488-531: LGTM - HTTP methods properly guarded.

All four HTTP methods (post, get, put, httpDelete) now await API key initialization before making requests. The implementation is consistent across all methods with clear comments.

Note: Effectiveness depends on the waitForApiKeyInit() fix (lines 56-65).

Comment on lines 93 to 125
export const initApiKey = async (): Promise<void> => {
// Return existing promise if already in progress
if (apiKeyInitPromise) return apiKeyInitPromise;

// Return immediately if already initialized
if (apiKeyInitialized) return;
apiKeyInitialized = true;

// Only Electron mode uses API key header auth
if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
try {
cachedApiKey = await window.electronAPI.getApiKey();
if (cachedApiKey) {
console.log('[HTTP Client] Using API key from Electron');
return;
// Create and store the promise so concurrent calls wait for the same initialization
apiKeyInitPromise = (async () => {
apiKeyInitialized = true;

// Only Electron mode uses API key header auth
if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
try {
cachedApiKey = await window.electronAPI.getApiKey();
if (cachedApiKey) {
console.log('[HTTP Client] Using API key from Electron');
return;
}
} catch (error) {
console.warn('[HTTP Client] Failed to get API key from Electron:', error);
}
} catch (error) {
console.warn('[HTTP Client] Failed to get API key from Electron:', error);
}
}

// In web mode, authentication is handled via HTTP-only cookies
console.log('[HTTP Client] Web mode - using cookie-based authentication');
// In web mode, authentication is handled via HTTP-only cookies
console.log('[HTTP Client] Web mode - using cookie-based authentication');
})();

return apiKeyInitPromise;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Major: Premature flag setting breaks coordination and prevents retry.

Setting apiKeyInitialized = true on line 102 (before the async API key fetch) creates multiple issues:

  1. Enables the race condition flagged in lines 56-65 by setting the flag before work completes
  2. Prevents retry: If Electron bridge is slow or fails temporarily, apiKeyInitialized blocks retry attempts
  3. Silent degradation: If getApiKey() fails (line 107-113), the catch logs a warning but initialization "succeeds," causing all subsequent HTTP requests to fail with 401s
🔎 Recommended fix: Set flag after async work completes

Move the flag assignment outside the IIFE, after the promise resolves:

 export const initApiKey = async (): Promise<void> => {
   // Return existing promise if already in progress
   if (apiKeyInitPromise) return apiKeyInitPromise;
 
   // Return immediately if already initialized
   if (apiKeyInitialized) return;
 
   // Create and store the promise so concurrent calls wait for the same initialization
   apiKeyInitPromise = (async () => {
-    apiKeyInitialized = true;
 
     // Only Electron mode uses API key header auth
     if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
       try {
         cachedApiKey = await window.electronAPI.getApiKey();
         if (cachedApiKey) {
           console.log('[HTTP Client] Using API key from Electron');
           return;
         }
       } catch (error) {
         console.warn('[HTTP Client] Failed to get API key from Electron:', error);
       }
     }
 
     // In web mode, authentication is handled via HTTP-only cookies
     console.log('[HTTP Client] Web mode - using cookie-based authentication');
   })();
 
+  await apiKeyInitPromise;
+  apiKeyInitialized = true;
   return apiKeyInitPromise;
 };

This ensures the flag is only set after initialization truly completes, enabling proper coordination and allowing retry on failure.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const initApiKey = async (): Promise<void> => {
// Return existing promise if already in progress
if (apiKeyInitPromise) return apiKeyInitPromise;
// Return immediately if already initialized
if (apiKeyInitialized) return;
apiKeyInitialized = true;
// Only Electron mode uses API key header auth
if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
try {
cachedApiKey = await window.electronAPI.getApiKey();
if (cachedApiKey) {
console.log('[HTTP Client] Using API key from Electron');
return;
// Create and store the promise so concurrent calls wait for the same initialization
apiKeyInitPromise = (async () => {
apiKeyInitialized = true;
// Only Electron mode uses API key header auth
if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
try {
cachedApiKey = await window.electronAPI.getApiKey();
if (cachedApiKey) {
console.log('[HTTP Client] Using API key from Electron');
return;
}
} catch (error) {
console.warn('[HTTP Client] Failed to get API key from Electron:', error);
}
} catch (error) {
console.warn('[HTTP Client] Failed to get API key from Electron:', error);
}
}
// In web mode, authentication is handled via HTTP-only cookies
console.log('[HTTP Client] Web mode - using cookie-based authentication');
// In web mode, authentication is handled via HTTP-only cookies
console.log('[HTTP Client] Web mode - using cookie-based authentication');
})();
return apiKeyInitPromise;
};
export const initApiKey = async (): Promise<void> => {
// Return existing promise if already in progress
if (apiKeyInitPromise) return apiKeyInitPromise;
// Return immediately if already initialized
if (apiKeyInitialized) return;
// Create and store the promise so concurrent calls wait for the same initialization
apiKeyInitPromise = (async () => {
// Only Electron mode uses API key header auth
if (typeof window !== 'undefined' && window.electronAPI?.getApiKey) {
try {
cachedApiKey = await window.electronAPI.getApiKey();
if (cachedApiKey) {
console.log('[HTTP Client] Using API key from Electron');
return;
}
} catch (error) {
console.warn('[HTTP Client] Failed to get API key from Electron:', error);
}
}
// In web mode, authentication is handled via HTTP-only cookies
console.log('[HTTP Client] Web mode - using cookie-based authentication');
})();
await apiKeyInitPromise;
apiKeyInitialized = true;
return apiKeyInitPromise;
};
🤖 Prompt for AI Agents
In apps/ui/src/lib/http-api-client.ts around lines 93 to 122, the code sets
apiKeyInitialized = true before awaiting the async API key fetch, which causes
premature success signaling, blocks retries on transient failures, and enables
the race condition; move the apiKeyInitialized assignment so it only runs after
the async IIFE resolves successfully (i.e., after cachedApiKey is obtained or
web-mode path completes), and on failure ensure apiKeyInitPromise is cleared (or
apiKeyInitialized remains false) so subsequent calls can retry; keep the pattern
of storing apiKeyInitPromise for concurrent callers but only mark initialization
complete after successful completion and clear/reset the promise on errors.

API requests were being made before initApiKey() completed, causing
401 Unauthorized errors on app startup in Electron mode.

Changes:
- Add waitForApiKeyInit() to track and await API key initialization
- Make HTTP methods (get/post/put/delete) wait for auth before requests
- Defer WebSocket connection until API key is ready
- Add explicit auth wait in useSettingsMigration hook

Fixes race condition introduced in PR AutoMaker-Org#321
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/ui/src/lib/http-api-client.ts (1)

56-65: Reorder checks for robustness: test promise existence before flag.

While the current implementation works because apiKeyInitialized is set only after the promise completes (line 120), the check order is conceptually backwards. Testing the flag first relies on implementation details of initApiKey() and creates fragile coupling.

Checking apiKeyInitPromise first better expresses the intent: "in-progress → completed → not started".

🔎 Recommended: Reorder checks to test promise existence first
 export const waitForApiKeyInit = (): Promise<void> => {
-  if (apiKeyInitialized) return Promise.resolve();
   if (apiKeyInitPromise) return apiKeyInitPromise;
+  if (apiKeyInitialized) return Promise.resolve();
   // If not started yet, start it now
   return initApiKey();
 };

This ordering is more intuitive and prevents future modifications to initApiKey() from accidentally introducing race conditions.

Based on learnings from past review comments.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f6c397 and f6ce03d.

📒 Files selected for processing (2)
  • apps/ui/src/hooks/use-settings-migration.ts
  • apps/ui/src/lib/http-api-client.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/ui/src/hooks/use-settings-migration.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/lib/http-api-client.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/lib/http-api-client.ts
🔇 Additional comments (3)
apps/ui/src/lib/http-api-client.ts (3)

93-125: Good: Flag now set after completion. Verify no-retry behavior is intentional.

The finally block correctly ensures apiKeyInitialized is set only after initialization completes, addressing the race condition from the past review comments.

However, the flag is set "regardless of success or failure" (line 119). If getApiKey() fails due to a transient error (e.g., Electron bridge not ready), initialization falls back to web mode and subsequent calls won't retry. Confirm this is the intended behavior—no retry on transient Electron failures.

Based on learnings from past review comments.


322-335: LGTM! Catch handler added as recommended.

The catch handler correctly addresses the past review comment. Attempting WebSocket connection even after API key initialization failure is appropriate, as cookie-based auth may still succeed in web mode.

Based on learnings from past review comments.


497-540: LGTM! HTTP methods correctly wait for API key initialization.

All HTTP methods now properly await waitForApiKeyInit() before sending requests, preventing the 401 errors on startup that this PR aims to fix. The implementation is consistent across all methods with clear explanatory comments.

@webdevcody webdevcody merged commit bd22323 into AutoMaker-Org:main Jan 1, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants