Skip to content

update main from test#1603

Merged
sweetmantech merged 11 commits into
mainfrom
test
Mar 27, 2026
Merged

update main from test#1603
sweetmantech merged 11 commits into
mainfrom
test

Conversation

@arpitgupta1214

@arpitgupta1214 arpitgupta1214 commented Mar 27, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added drag-and-drop sandbox file upload UI and an upload endpoint for submitting files (100MB limit).
    • Added client-side file-upload flow with toast feedback and a file-tree drop integration.
  • Refactor

    • Chat interactions now use token-based authentication and external API endpoints; internal chat proxy routes and non-streaming/streaming API handlers were removed.

CTO Agent and others added 3 commits March 27, 2026 12:28
Integrates react-dropzone drag-and-drop with the /files page to upload
files to GitHub sandbox repos via POST /api/sandboxes/files. Shows
upload overlay, progress state, and toast notifications on completion.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
migrate to dedicated api for chat endpoints
@vercel

vercel Bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
recoup-chat Ready Ready Preview Mar 28, 2026 10:37pm

Request Review

@coderabbitai

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 83f2f106-9c85-4794-b383-5a1523d80349

📥 Commits

Reviewing files that changed from the base of the PR and between 466550d and cf8a178.

⛔ Files ignored due to path filters (2)
  • package.json is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
📒 Files selected for processing (7)
  • app/api/sandbox/upload/route.ts
  • components/Sandboxes/NoSandboxFiles.tsx
  • components/Sandboxes/SandboxDropZone.tsx
  • components/Sandboxes/SandboxFileTree.tsx
  • hooks/useSandboxFileDrop.ts
  • lib/sandboxes/findFileNode.ts
  • lib/sandboxes/uploadSandboxFiles.ts

📝 Walkthrough

Walkthrough

Removed local chat API routes and proxy utility; updated client chat hook to call external chats API with access tokens. Added a sandbox drag-and-drop upload flow: new upload API, client components, upload hook, and helper libs to upload files to Vercel Blob and notify backend.

Changes

Cohort / File(s) Summary
Deleted Chat API Routes
app/api/chat/create/route.ts, app/api/chat/generate/route.ts, app/api/chat/route.ts
Removed local POST/OPTIONS handlers that validated, created rooms, proxied or forwarded chat/generation requests, and handled streaming/non-streaming proxying.
Removed Chat Proxy Utility
lib/chat/proxyToApiChat.ts
Deleted proxyToApiChat function and ProxyOptions type used to forward requests to upstream recoup-api with header/CORS/deprecation handling.
Client Chat Hook Update
hooks/useCreateChat.tsx
Switched hook to use useAccessToken() and NEW_API_BASE_URL; now calls external POST /api/chats with Authorization header and adapts to new response shape.
Sandbox Upload API
app/api/sandbox/upload/route.ts
Added POST handler to initiate Vercel Blob uploads; validates clientPayload token via onBeforeGenerateToken, enforces 100MB limit, and returns JSON success/error payloads.
Drag-and-Drop Components
components/Sandboxes/NoSandboxFiles.tsx, components/Sandboxes/SandboxDropZone.tsx, components/Sandboxes/SandboxFileTree.tsx
Added NoSandboxFiles and SandboxDropZone components and updated SandboxFileTree to integrate drag-and-drop UI, showing dropzone when empty and wrapping file list when present.
Sandbox Upload Hook
hooks/useSandboxFileDrop.ts
New hook that obtains access token, computes target path, calls uploadSandboxFiles, exposes handleFilesDropped and uploading, and shows toasts on success/error.
Sandbox Libs
lib/sandboxes/findFileNode.ts, lib/sandboxes/uploadSandboxFiles.ts
Added findFileNode to locate nodes by path in filetree. Added uploadSandboxFiles to upload files to Vercel Blob and POST file references to external /api/sandboxes/files endpoint, handling errors and response shape.

Sequence Diagram

sequenceDiagram
    participant Client
    participant DropZone as "DropZone UI"
    participant Hook as "useSandboxFileDrop"
    participant Blob as "Vercel Blob Upload\n(`@vercel/blob`)"
    participant Backend as "External API\n/ api/sandboxes/files"

    rect rgba(100,150,240,0.5)
    Note over Client,Backend: Sandbox upload flow
    Client->>DropZone: user drops files
    DropZone->>Hook: handleFilesDropped(files)
    Hook->>Client: fetch access token (usePrivy)
    Hook->>Blob: upload each file (clientPayload includes token)
    Blob-->>Hook: returns blob URLs
    Hook->>Backend: POST /api/sandboxes/files + Authorization: Bearer <token> with blob refs
    Backend-->>Hook: returns status (success|error)
    Hook-->>Client: resolve mutation, show toasts and refetch filetree
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Files fall like leaves to cloud,
A token opens up the shroud,
Drag, drop, a tiny hum—
Blobs and endpoints now become,
New paths stitched in code aloud. ✨

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Solid & Clean Code ⚠️ Warning PR violates SRP and DRY principles; useCreateChat hook combines token management, optimistic state, and API communication; removal of centralized proxyToApiChat creates duplication; insufficient error handling for null accessToken creates indeterminate state. Extract fetch logic to reusable lib/api utility; separate token validation into dedicated effect; implement explicit error states; create typed API response handler for consistent error handling across hooks.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test

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.

- Add /api/sandbox-upload route for generating presigned blob tokens
- Update uploadSandboxFiles to upload to Vercel Blob first, then
  pass blob URLs to the API (bypasses 4.5MB serverless limit)
- Add @vercel/blob dependency

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
hooks/useCreateChat.tsx (1)

95-103: ⚠️ Potential issue | 🟠 Major

Guard createChat to prevent duplicate POST writes.

This effect can rerun while isOptimisticChatItem is still true (dependency identity changes), which can trigger duplicate POST /api/chats calls. Add a one-shot/idempotency guard per chat id.

🔧 Suggested fix
-import { useEffect } from "react";
+import { useEffect, useRef } from "react";
...
+  const createdChatIdsRef = useRef<Set<string>>(new Set());
   const accessToken = useAccessToken();

   useEffect(() => {
     if (!isOptimisticChatItem || !accessToken) return;
+    const chatId = (chatRoom as Conversation).id;
+    if (!chatId || createdChatIdsRef.current.has(chatId)) return;
+    createdChatIdsRef.current.add(chatId);

     const createChat = async () => {
       try {
...
-          chatId: (chatRoom as Conversation).id,
+          chatId,
...
-    createChat();
+    void createChat();
   }, [
     isOptimisticChatItem,
-    chatRoom,
+    (chatRoom as Conversation).id,
     selectedArtist?.account_id,
     accessToken,
     setDisplayName,
     refetchConversations,
   ]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useCreateChat.tsx` around lines 95 - 103, The effect calling createChat
in useCreateChat can fire multiple times and cause duplicate POST /api/chats
calls; add a one-shot/idempotency guard keyed by chat id (e.g., chatRoom.id or
composed from chatRoom + selectedArtist?.account_id) using a module-level or
hook-level ref/Set (e.g., createdChatIds or inFlightChatIds) and check it before
invoking createChat, mark the id as in-flight/created immediately when calling,
and only clear/reset on a determinative failure path; ensure the guard is
consulted in the effect dependencies (where isOptimisticChatItem, chatRoom,
selectedArtist?.account_id, accessToken, setDisplayName, refetchConversations
are used) so duplicate POSTs are prevented while preserving retry on real
failures.
🤖 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/useCreateChat.tsx`:
- Line 27: The early return on "if (!isOptimisticChatItem || !accessToken)
return;" silently abandons optimistic chats when token retrieval fails; change
this to explicitly handle the missing-token case by detecting the error path
from useAccessToken (e.g., accessToken === null or an error flag) and
dispatching a reconciliation/failure for the optimistic item instead of
returning. Update the flow in useCreateChat.tsx so that when
isOptimisticChatItem is true but accessToken is missing you call the existing
optimistic reconciliation routine (or add a new
markChatFailed/rollbackOptimisticChat function) and surface an error (e.g., set
a failed state or show a toast) so the optimistic chat isn’t left hanging while
still proceeding when a valid accessToken exists.

---

Outside diff comments:
In `@hooks/useCreateChat.tsx`:
- Around line 95-103: The effect calling createChat in useCreateChat can fire
multiple times and cause duplicate POST /api/chats calls; add a
one-shot/idempotency guard keyed by chat id (e.g., chatRoom.id or composed from
chatRoom + selectedArtist?.account_id) using a module-level or hook-level
ref/Set (e.g., createdChatIds or inFlightChatIds) and check it before invoking
createChat, mark the id as in-flight/created immediately when calling, and only
clear/reset on a determinative failure path; ensure the guard is consulted in
the effect dependencies (where isOptimisticChatItem, chatRoom,
selectedArtist?.account_id, accessToken, setDisplayName, refetchConversations
are used) so duplicate POSTs are prevented while preserving retry on real
failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3257bc5-37ab-4a4e-be17-8de75627c926

📥 Commits

Reviewing files that changed from the base of the PR and between 61ec725 and 466550d.

⛔ Files ignored due to path filters (2)
  • lib/chat/__tests__/proxyToApiChat.test.ts is excluded by !**/*.test.* and included by lib/**
  • types/Chat.tsx is excluded by none and included by none
📒 Files selected for processing (5)
  • app/api/chat/create/route.ts
  • app/api/chat/generate/route.ts
  • app/api/chat/route.ts
  • hooks/useCreateChat.tsx
  • lib/chat/proxyToApiChat.ts
💤 Files with no reviewable changes (4)
  • app/api/chat/route.ts
  • app/api/chat/generate/route.ts
  • app/api/chat/create/route.ts
  • lib/chat/proxyToApiChat.ts

Comment thread hooks/useCreateChat.tsx

useEffect(() => {
if (!isOptimisticChatItem) return;
if (!isOptimisticChatItem || !accessToken) return;

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 | 🟠 Major

Handle missing token with an explicit failure path.

At Line 27, returning on !accessToken silently strands optimistic chats when token retrieval fails (null is used for both “not loaded yet” and “error” in useAccessToken). Add an explicit error/reconciliation path so optimistic state is not left hanging.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useCreateChat.tsx` at line 27, The early return on "if
(!isOptimisticChatItem || !accessToken) return;" silently abandons optimistic
chats when token retrieval fails; change this to explicitly handle the
missing-token case by detecting the error path from useAccessToken (e.g.,
accessToken === null or an error flag) and dispatching a reconciliation/failure
for the optimistic item instead of returning. Update the flow in
useCreateChat.tsx so that when isOptimisticChatItem is true but accessToken is
missing you call the existing optimistic reconciliation routine (or add a new
markChatFailed/rollbackOptimisticChat function) and surface an error (e.g., set
a failed state or show a toast) so the optimistic chat isn’t left hanging while
still proceeding when a valid accessToken exists.

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

Copy link
Copy Markdown

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: 466550d50e

ℹ️ 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".

Comment thread hooks/useCreateChat.tsx

useEffect(() => {
if (!isOptimisticChatItem) return;
if (!isOptimisticChatItem || !accessToken) return;

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 Persist optimistic chats without waiting on access token

This early return can drop newly-created optimistic chats when the user sends a message before Privy token hydration completes. handleSendMessage adds optimistic items immediately, but this hook now does nothing until accessToken exists; meanwhile conversation data is keyed by token, so when the key flips from null to a token the optimistic entry is replaced and the create call never runs. In that flow, the new chat can disappear from Recent Chats instead of being persisted via /api/chats.

Useful? React with 👍 / 👎.

sweetmantech and others added 6 commits March 27, 2026 17:20
- Extract file drop logic to useSandboxFileDrop hook (OCP)
- Extract drag-n-drop wrapper to SandboxDropZone component (OCP)
- Move route from sandbox-upload to sandbox/upload (KISS)
- Add auth check to blob upload endpoint
- Move JSON parsing inside try-catch
- Fix file vs directory detection using FileNode.type instead of dot heuristic
- Parallelize blob uploads with Promise.all
- Add ARIA labels for accessibility
- Use cn() utility for class merging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract NoSandboxFiles to its own component (SRP)
- Extract findFileNode to lib/sandboxes/findFileNode.ts (SRP)
- Use tanstack useMutation in useSandboxFileDrop for cleaner state management

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The blob client controls its own request headers, so we validate
the access token passed via clientPayload in onBeforeGenerateToken.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…chat

feat: drag-and-drop file upload for sandbox file tree
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