Skip to content

agent: @U0AJM7X8FBR currently, after a couple minutes of the chat app being ope#1579

Open
recoup-coding-agent wants to merge 1 commit intotestfrom
agent/-u0ajm7x8fbr-currently--after--1773422481875
Open

agent: @U0AJM7X8FBR currently, after a couple minutes of the chat app being ope#1579
recoup-coding-agent wants to merge 1 commit intotestfrom
agent/-u0ajm7x8fbr-currently--after--1773422481875

Conversation

@recoup-coding-agent
Copy link
Copy Markdown
Collaborator

@recoup-coding-agent recoup-coding-agent commented Mar 13, 2026

Automated PR from coding agent.

Summary by CodeRabbit

  • New Features
    • Enhanced chat messaging with fresh token authentication for improved security and reliability. Messages now include automatically refreshed authorization credentials before being sent, ensuring all requests are authenticated with current access tokens.

Privy access tokens expire, but the token was only fetched once on mount
via useAccessToken and cached in React state. After expiry, subsequent
chat requests were sent with the stale token and failed with 401 errors.

Now getAccessToken() is called right before each sendMessage() call so
Privy's SDK can transparently refresh the token if needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
recoup-chat Ready Ready Preview Mar 13, 2026 5:26pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 13, 2026

📝 Walkthrough

Walkthrough

The chat hook now integrates Privy-based authentication for token refresh. Before sending messages, the hook retrieves a fresh access token via getAccessToken and conditionally includes an Authorization header in requests. The handleSubmit function is made asynchronous to await token retrieval, with dependency arrays updated accordingly.

Changes

Cohort / File(s) Summary
Token Refresh Integration
hooks/useVercelChat.ts
Integrated Privy's usePrivy hook to obtain getAccessToken; modified handleSubmit and handleSendQueryMessages to be async, retrieve fresh tokens, and conditionally attach Authorization headers to requests; updated dependency arrays to include getAccessToken in token-dependent callbacks.

Sequence Diagram

sequenceDiagram
    participant Client as React Component
    participant Hook as useVercelChat Hook
    participant Privy as Privy Auth
    participant API as Chat API

    Client->>Hook: Call handleSubmit(message)
    Hook->>Privy: getAccessToken()
    Privy-->>Hook: Fresh access token
    Hook->>Hook: Construct requestOptions with<br/>Authorization header
    Hook->>API: POST message with token
    API-->>Hook: Response
    Hook-->>Client: Updated chat state
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🔐 Tokens refresh like morning dew,
Privy guards what's old and new,
Headers dressed in fresh auth's grace,
Async flows now set the pace,
Chats secure in every case! 💬

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Solid & Clean Code ⚠️ Warning Code violates DRY principle with identical token refresh logic repeated at lines 239-248 and 325-334; headers are replaced instead of merged, losing existing headers. Extract token refresh and header merging into a dedicated helper function that spreads existing headers: createAuthenticatedRequestOptions(chatRequestOptions, freshToken).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch agent/-u0ajm7x8fbr-currently--after--1773422481875
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae65b98fee

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


sendMessage(payload, chatRequestOptions);
// Get a fresh token at send time so expired tokens are never used
const freshToken = await getAccessToken();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Mark send state before awaiting access token

Awaiting getAccessToken() before sendMessage() leaves the form in a sendable state while token refresh is in progress; when refresh takes noticeable time (the exact expiry case this patch targets), users can press Enter/click submit again and enqueue duplicate copies of the same prompt, causing duplicate model runs and credit usage. This path previously submitted immediately, so the new await introduces a regression unless resubmission is blocked before the token call.

Useful? React with 👍 / 👎.

async (initialMessage: UIMessage) => {
silentlyUpdateUrl();
sendMessage(initialMessage, chatRequestOptions);
const freshToken = await getAccessToken();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid re-triggering initial send during token refresh

The initial-message path now waits for getAccessToken() before calling sendMessage(), which creates a window where status is still ready and messages are unchanged; if a rerender updates dependencies (for example model initialization updates chatRequestOptions), the effect can invoke this callback again and send the initial prompt twice. This duplicate-send condition is specific to slower token retrieval and was not present when sendMessage() happened synchronously.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
hooks/useVercelChat.ts (1)

252-254: ⚠️ Potential issue | 🟠 Major

append function doesn't use fresh token pattern, creating inconsistency.

The append function still uses chatRequestOptions directly without refreshing the token, while handleSubmit and handleSendQueryMessages now fetch a fresh token before sending. This could lead to the same 401 errors the PR is fixing if append is called after token expiry.

🔧 Proposed fix to make append consistent
-  const append = (message: UIMessage) => {
-    sendMessage(message, chatRequestOptions);
+  const append = useCallback(async (message: UIMessage) => {
+    const freshToken = await getAccessToken();
+    const requestOptions = freshToken
+      ? {
+          ...chatRequestOptions,
+          headers: { ...chatRequestOptions.headers, Authorization: `Bearer ${freshToken}` },
+        }
+      : chatRequestOptions;
+    sendMessage(message, requestOptions);
+  }, [getAccessToken, chatRequestOptions, sendMessage]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useVercelChat.ts` around lines 252 - 254, The append function uses the
stale chatRequestOptions causing token-expiry 401s; update append (in
hooks/useVercelChat.ts) to follow the same fresh-token pattern as handleSubmit
and handleSendQueryMessages by calling getVercelEdgeToken() (or the existing
token-refresh helper), merge the returned token into a new chatRequestOptions
object, and then call sendMessage(message, updatedChatRequestOptions) so
sendMessage always receives a current token.
🧹 Nitpick comments (1)
hooks/useVercelChat.ts (1)

239-248: Consider extracting token-refresh logic to reduce duplication.

The pattern of fetching a fresh token and building requestOptions is repeated in handleSubmit, handleSendQueryMessages, and should be added to append. A small helper would centralize this logic.

♻️ Optional helper extraction
// Add inside the hook, before the callbacks
const buildRequestOptionsWithFreshToken = useCallback(async () => {
  const freshToken = await getAccessToken();
  return freshToken
    ? {
        ...chatRequestOptions,
        headers: { ...chatRequestOptions.headers, Authorization: `Bearer ${freshToken}` },
      }
    : chatRequestOptions;
}, [getAccessToken, chatRequestOptions]);

Then use it in each location:

const requestOptions = await buildRequestOptionsWithFreshToken();
sendMessage(payload, requestOptions);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useVercelChat.ts` around lines 239 - 248, Extract the repeated
token-refresh + options-build logic into a single helper (e.g.
buildRequestOptionsWithFreshToken) inside the hook and use it from handleSubmit,
handleSendQueryMessages and append; the helper should call getAccessToken(), and
if a token exists return { ...chatRequestOptions, headers: {
...chatRequestOptions.headers, Authorization: `Bearer ${token}` } } else return
chatRequestOptions, and register it with useCallback (dependencies:
getAccessToken, chatRequestOptions) before replacing the existing ad-hoc
token-fetch + requestOptions construction and calling sendMessage(payload,
requestOptions).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@hooks/useVercelChat.ts`:
- Around line 325-332: The current token-injection before calling sendMessage
overwrites any existing headers on chatRequestOptions; update the merge so
headers = { ...(chatRequestOptions.headers || {}), Authorization: `Bearer
${freshToken}` } when building requestOptions (inside the getAccessToken branch)
so existing headers are preserved—apply this change where getAccessToken,
chatRequestOptions, initialMessage and sendMessage are used.
- Around line 239-248: The code overwrites chatRequestOptions.headers when
freshToken exists, dropping any existing headers; fix by creating requestOptions
from chatRequestOptions (or an empty object) and set headers to a new object
that merges existing chatRequestOptions.headers with the Authorization header
(so Authorization wins but other headers are preserved), do not mutate
chatRequestOptions, and then pass this merged requestOptions into sendMessage;
reference getAccessToken, chatRequestOptions, freshToken, and sendMessage when
locating the change.

---

Outside diff comments:
In `@hooks/useVercelChat.ts`:
- Around line 252-254: The append function uses the stale chatRequestOptions
causing token-expiry 401s; update append (in hooks/useVercelChat.ts) to follow
the same fresh-token pattern as handleSubmit and handleSendQueryMessages by
calling getVercelEdgeToken() (or the existing token-refresh helper), merge the
returned token into a new chatRequestOptions object, and then call
sendMessage(message, updatedChatRequestOptions) so sendMessage always receives a
current token.

---

Nitpick comments:
In `@hooks/useVercelChat.ts`:
- Around line 239-248: Extract the repeated token-refresh + options-build logic
into a single helper (e.g. buildRequestOptionsWithFreshToken) inside the hook
and use it from handleSubmit, handleSendQueryMessages and append; the helper
should call getAccessToken(), and if a token exists return {
...chatRequestOptions, headers: { ...chatRequestOptions.headers, Authorization:
`Bearer ${token}` } } else return chatRequestOptions, and register it with
useCallback (dependencies: getAccessToken, chatRequestOptions) before replacing
the existing ad-hoc token-fetch + requestOptions construction and calling
sendMessage(payload, requestOptions).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 38042866-a837-4a5c-9989-8a56e81d527f

📥 Commits

Reviewing files that changed from the base of the PR and between 0371429 and ae65b98.

📒 Files selected for processing (1)
  • hooks/useVercelChat.ts

Comment on lines +239 to +248
// Get a fresh token at send time so expired tokens are never used
const freshToken = await getAccessToken();
const requestOptions = freshToken
? {
...chatRequestOptions,
headers: { Authorization: `Bearer ${freshToken}` },
}
: chatRequestOptions;

sendMessage(payload, requestOptions);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Headers are replaced instead of merged, potentially losing other headers.

When freshToken exists, the code overwrites headers entirely rather than merging with existing headers from chatRequestOptions. If chatRequestOptions.headers contains additional headers (now or in the future), they will be silently dropped.

🔧 Proposed fix to merge headers
     // Get a fresh token at send time so expired tokens are never used
     const freshToken = await getAccessToken();
     const requestOptions = freshToken
       ? {
           ...chatRequestOptions,
-          headers: { Authorization: `Bearer ${freshToken}` },
+          headers: { ...chatRequestOptions.headers, Authorization: `Bearer ${freshToken}` },
         }
       : chatRequestOptions;
📝 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
// Get a fresh token at send time so expired tokens are never used
const freshToken = await getAccessToken();
const requestOptions = freshToken
? {
...chatRequestOptions,
headers: { Authorization: `Bearer ${freshToken}` },
}
: chatRequestOptions;
sendMessage(payload, requestOptions);
// Get a fresh token at send time so expired tokens are never used
const freshToken = await getAccessToken();
const requestOptions = freshToken
? {
...chatRequestOptions,
headers: { ...(chatRequestOptions.headers || {}), Authorization: `Bearer ${freshToken}` },
}
: chatRequestOptions;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useVercelChat.ts` around lines 239 - 248, The code overwrites
chatRequestOptions.headers when freshToken exists, dropping any existing
headers; fix by creating requestOptions from chatRequestOptions (or an empty
object) and set headers to a new object that merges existing
chatRequestOptions.headers with the Authorization header (so Authorization wins
but other headers are preserved), do not mutate chatRequestOptions, and then
pass this merged requestOptions into sendMessage; reference getAccessToken,
chatRequestOptions, freshToken, and sendMessage when locating the change.

Comment on lines +325 to +332
const freshToken = await getAccessToken();
const requestOptions = freshToken
? {
...chatRequestOptions,
headers: { Authorization: `Bearer ${freshToken}` },
}
: chatRequestOptions;
sendMessage(initialMessage, requestOptions);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same headers merge issue applies here.

Consistent with the earlier comment on handleSubmit, this should also spread existing headers to avoid losing them.

🔧 Proposed fix
       const freshToken = await getAccessToken();
       const requestOptions = freshToken
         ? {
             ...chatRequestOptions,
-            headers: { Authorization: `Bearer ${freshToken}` },
+            headers: { ...chatRequestOptions.headers, Authorization: `Bearer ${freshToken}` },
           }
         : chatRequestOptions;
📝 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
const freshToken = await getAccessToken();
const requestOptions = freshToken
? {
...chatRequestOptions,
headers: { Authorization: `Bearer ${freshToken}` },
}
: chatRequestOptions;
sendMessage(initialMessage, requestOptions);
const freshToken = await getAccessToken();
const requestOptions = freshToken
? {
...chatRequestOptions,
headers: { ...chatRequestOptions.headers, Authorization: `Bearer ${freshToken}` },
}
: chatRequestOptions;
sendMessage(initialMessage, requestOptions);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useVercelChat.ts` around lines 325 - 332, The current token-injection
before calling sendMessage overwrites any existing headers on
chatRequestOptions; update the merge so headers = {
...(chatRequestOptions.headers || {}), Authorization: `Bearer ${freshToken}` }
when building requestOptions (inside the getAccessToken branch) so existing
headers are preserved—apply this change where getAccessToken,
chatRequestOptions, initialMessage and sendMessage are used.

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.

1 participant