Skip to content

Main chrome ext fix#268

Merged
1shCha merged 4 commits intomainfrom
main_chrome_ext_fix
Mar 30, 2026
Merged

Main chrome ext fix#268
1shCha merged 4 commits intomainfrom
main_chrome_ext_fix

Conversation

@1shCha
Copy link
Copy Markdown
Contributor

@1shCha 1shCha commented Mar 30, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added file import functionality to workspaces with automatic duplicate naming and folder organization support.
  • Improvements

    • Enhanced real-time synchronization for workspace and OCR events.
    • Improved visual indicators in layout split handles.
  • Documentation

    • Added developer guidance for local setup and architecture overview.

1shCha added 4 commits March 29, 2026 02:51
  When a PDF was imported via the Chrome extension, the workspace card
  would flicker between reading and done states. Two bugs caused this:

  1. persistOcrResults wrote BULK_ITEMS_PATCHED to the DB but never
     broadcast it over Supabase Realtime, so connected clients only
     learned of OCR completion via a manual refetch — not live. Fixed by
     broadcasting the BULK_ITEMS_PATCHED event via service role key after
     the DB write, mirroring the pattern the import route uses for
     BULK_ITEMS_CREATED. The DB-assigned version is now returned from
     appendWorkspaceEvent and included in the broadcast payload so the
     client cache maintains correct event ordering.

  2. refetchOnWindowFocus: 'always' caused a stale refetch (started
     before OCR completed) to race the realtime broadcast and overwrite
     done back to processing. Since both BULK_ITEMS_CREATED and
     BULK_ITEMS_PATCHED are now broadcast server-side, the safety-net
     refetch is unnecessary and has been disabled.
iMerge branch 'main' into main_chrome_ext_fix
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Mar 30, 2026

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

Project Deployment Actions Updated (UTC)
thinkex Ready Ready Preview, Comment Mar 30, 2026 11:11pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 30, 2026

📝 Walkthrough

Walkthrough

Added comprehensive development documentation (CLAUDE.md), implemented workspace folder retrieval and file import APIs with OCR triggering, enhanced realtime event broadcasting for OCR result persistence, improved workspace state loading with folder filtering, updated styling in layout components, and streamlined self-event filtering in realtime synchronization.

Changes

Cohort / File(s) Summary
Documentation
CLAUDE.md
Added developer guide covering pnpm commands, ESLint constraints, architectural overview (Next.js 16, event sourcing, Zustand state, Drizzle ORM), AI tooling, authentication, storage adapters, and path aliases.
API Routes
src/app/api/workspaces/[id]/folders/route.ts, src/app/api/workspaces/[id]/import/route.ts
Added GET /folders endpoint to retrieve workspace folders; added POST /import endpoint with file validation, workspace state loading, bulk item creation with retry logic, OCR triggering, and realtime broadcasting.
Workspace State & Persistence
src/lib/workspace/state-loader.ts, src/workflows/ocr-dispatch/steps/persist-results.ts
Added loadWorkspaceFolders() function with event pagination; updated appendWorkspaceEvent() to return version number; integrated Supabase realtime broadcasting on OCR result persistence with error handling.
Realtime & Synchronization
src/hooks/workspace/use-workspace-realtime.ts, src/hooks/workspace/use-workspace-events.ts
Removed self-event filtering conditional (relying on Supabase broadcast.self: false config); updated refetch comment for clarity.
Styling & Configuration
src/app/globals.css, src/components/layout/DashboardLayout.tsx, public/.well-known/workflow/v1/manifest.json
Removed SCSS imports and color-scheme declarations; added border styling to resizable handles; reordered step definitions in workflow manifest.

Sequence Diagrams

sequenceDiagram
    actor Client
    participant ImportAPI as Import API<br/>(POST /import)
    participant WorkspaceState as Workspace State<br/>(state-loader)
    participant Database as Database<br/>(append_workspace_event)
    participant RealtimeDB as Realtime<br/>(Supabase)
    participant OCRStartAPI as OCR Start API<br/>(/api/ocr/start)

    Client->>ImportAPI: POST files with metadata
    ImportAPI->>ImportAPI: Validate files & payload
    ImportAPI->>WorkspaceState: loadWorkspaceState(id)
    WorkspaceState->>Database: Fetch latest snapshot & events
    Database-->>WorkspaceState: Return current state
    ImportAPI->>ImportAPI: Resolve name conflicts, build items
    ImportAPI->>Database: appendBulkItemsWithRetry()
    Database-->>ImportAPI: Return version
    ImportAPI->>RealtimeDB: Broadcast workspace:id:events
    RealtimeDB-->>ImportAPI: Acknowledge
    ImportAPI->>OCRStartAPI: Trigger OCR for items
    OCRStartAPI-->>ImportAPI: Return ocrRunId
    ImportAPI-->>Client: { success, itemIds, ocrRunId }
Loading
sequenceDiagram
    participant OCRStep as OCR Workflow Step<br/>(persist-results)
    participant Database as Database<br/>(append_workspace_event)
    participant RealtimeService as Realtime Service<br/>(Supabase)
    participant Client as Connected Clients

    OCRStep->>Database: appendWorkspaceEvent(OCR_COMPLETED)
    Database-->>OCRStep: version (number)
    OCRStep->>RealtimeService: Initialize client & send broadcast
    RealtimeService->>RealtimeService: Publish on workspace:id:events
    RealtimeService-->>Client: Deliver workspace_event payload
    RealtimeService-->>OCRStep: Acknowledge
    OCRStep->>OCRStep: Log any broadcast errors (non-blocking)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • thinkex#205: Implements parallel server-side persistence and broadcasting for OCR results with similar appendWorkspaceEvent return type changes and realtime event delivery patterns.

Poem

🐰 Hopping through folders, importing with cheer,
Files find their home in the workspace sphere,
Realtime whispers guide OCR's way,
Snapshots and events keep chaos at bay! 🌟

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Main chrome ext fix' is vague and does not clearly describe the actual changes in the pull request, which include API routes for workspace folders/imports, OCR workflow updates, CSS changes, and documentation. Provide a more specific title that captures the main changes, such as 'Add workspace folders API and import endpoint with OCR integration' or 'Refactor workspace state management and add file import workflow'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 main_chrome_ext_fix

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
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/app/api/workspaces/[id]/import/route.ts">

<violation number="1" location="src/app/api/workspaces/[id]/import/route.ts:90">
P2: No upper bound on the number of files per import request. An unbounded `files` array can be abused to cause excessive CPU (duplicate-name resolution is quadratic), memory (large JSON payload), and database load. Add a reasonable maximum (e.g., 50 or 100 files) and return a 400 if exceeded.</violation>

<violation number="2" location="src/app/api/workspaces/[id]/import/route.ts:202">
P1: Self-fetching the same Next.js server (`/api/ocr/start`) is an anti-pattern that adds latency, wastes a connection, and can deadlock in serverless environments. Import and call the OCR start logic directly instead of making an HTTP round-trip to yourself. The manual cookie forwarding also makes this fragile — any auth middleware changes would silently break this path.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

let ocrRunId: string | null = null;
try {
const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000";
const ocrResponse = await fetch(`${appUrl}/api/ocr/start`, {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

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

P1: Self-fetching the same Next.js server (/api/ocr/start) is an anti-pattern that adds latency, wastes a connection, and can deadlock in serverless environments. Import and call the OCR start logic directly instead of making an HTTP round-trip to yourself. The manual cookie forwarding also makes this fragile — any auth middleware changes would silently break this path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/app/api/workspaces/[id]/import/route.ts, line 202:

<comment>Self-fetching the same Next.js server (`/api/ocr/start`) is an anti-pattern that adds latency, wastes a connection, and can deadlock in serverless environments. Import and call the OCR start logic directly instead of making an HTTP round-trip to yourself. The manual cookie forwarding also makes this fragile — any auth middleware changes would silently break this path.</comment>

<file context>
@@ -0,0 +1,224 @@
+  let ocrRunId: string | null = null;
+  try {
+    const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000";
+    const ocrResponse = await fetch(`${appUrl}/api/ocr/start`, {
+      method: "POST",
+      headers: { "Content-Type": "application/json", cookie: request.headers.get("cookie") ?? "" },
</file context>
Fix with Cubic

const body = await request.json();
const files: ImportFile[] = Array.isArray(body.files) ? body.files : [];

if (files.length === 0) {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

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

P2: No upper bound on the number of files per import request. An unbounded files array can be abused to cause excessive CPU (duplicate-name resolution is quadratic), memory (large JSON payload), and database load. Add a reasonable maximum (e.g., 50 or 100 files) and return a 400 if exceeded.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/app/api/workspaces/[id]/import/route.ts, line 90:

<comment>No upper bound on the number of files per import request. An unbounded `files` array can be abused to cause excessive CPU (duplicate-name resolution is quadratic), memory (large JSON payload), and database load. Add a reasonable maximum (e.g., 50 or 100 files) and return a 400 if exceeded.</comment>

<file context>
@@ -0,0 +1,224 @@
+  const body = await request.json();
+  const files: ImportFile[] = Array.isArray(body.files) ? body.files : [];
+
+  if (files.length === 0) {
+    return NextResponse.json({ error: "At least one file is required" }, { status: 400 });
+  }
</file context>
Fix with Cubic

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (3)
CLAUDE.md (1)

71-71: Add language specifier to fenced code block.

The code block starting at line 71 is missing a language specifier. For a path listing, use text or plaintext to satisfy markdownlint and improve rendering consistency.

Proposed fix
-```
+```text
 src/app/api/         # API routes (auth, chat, cards, pdf, youtube, deep-research)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` at line 71, In CLAUDE.md locate the fenced code block that
contains the repository path listing (the block that begins with ``` and
contains lines like "src/app/api/         # API routes (auth, chat, cards, pdf,
youtube, deep-research)") and change the opening fence to include a language
specifier (e.g., ```text or ```plaintext) so markdownlint passes and rendering
is consistent.
src/lib/workspace/state-loader.ts (1)

59-59: Consider defining a type for raw event query results.

Multiple any types are used for DB query results (lines 59, 78, 80, 99, 107). While the code safely maps to WorkspaceEvent downstream, defining an interface for the raw query shape would improve maintainability.

Proposed type definition
interface RawEventRow {
  eventId: string;
  eventType: string;
  payload: unknown;
  timestamp: string | number;
  userId: string;
  userName: string | null;
  version: number;
}

// Then use:
let eventsData: RawEventRow[] = [];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/workspace/state-loader.ts` at line 59, Define a concrete type for raw
DB rows and replace the loose any[] usages: create an interface (e.g.,
RawEventRow with fields eventId, eventType, payload, timestamp, userId,
userName, version) and change declarations like let eventsData: any[] to let
eventsData: RawEventRow[]; update other any-typed query result variables in this
file (the other occurrences around the mappings to WorkspaceEvent) to use
RawEventRow so the mapping logic (in functions/methods that convert RawEventRow
-> WorkspaceEvent) is strongly typed and safer to maintain.
src/hooks/workspace/use-workspace-realtime.ts (1)

15-17: Stale interface documentation for currentUserId.

The JSDoc comment says currentUserId is used "to filter out own events," but after this PR, self-filtering is handled by the Supabase channel config (broadcast: { self: false }), not by currentUserId in the effect. The field is still destructured at line 46 but never used.

Consider updating the comment or removing currentUserId from the interface if it's truly unused.

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

In `@src/hooks/workspace/use-workspace-realtime.ts` around lines 15 - 17, The
JSDoc for WorkspaceRealtimeOptions incorrectly claims currentUserId is used to
"filter out own events" but self-filtering is now done via the Supabase channel
broadcast config; remove currentUserId from the WorkspaceRealtimeOptions
interface and from any destructuring (the local variable currently being pulled
into the effect), or if you prefer to keep the field for future use, update the
JSDoc to reflect that it is unused by the effect and not relied on for
self-filtering; ensure no unused variable warnings remain (check the
destructuring site in useWorkspaceRealtime and the interface definition
WorkspaceRealtimeOptions).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@CLAUDE.md`:
- Line 71: In CLAUDE.md locate the fenced code block that contains the
repository path listing (the block that begins with ``` and contains lines like
"src/app/api/         # API routes (auth, chat, cards, pdf, youtube,
deep-research)") and change the opening fence to include a language specifier
(e.g., ```text or ```plaintext) so markdownlint passes and rendering is
consistent.

In `@src/hooks/workspace/use-workspace-realtime.ts`:
- Around line 15-17: The JSDoc for WorkspaceRealtimeOptions incorrectly claims
currentUserId is used to "filter out own events" but self-filtering is now done
via the Supabase channel broadcast config; remove currentUserId from the
WorkspaceRealtimeOptions interface and from any destructuring (the local
variable currently being pulled into the effect), or if you prefer to keep the
field for future use, update the JSDoc to reflect that it is unused by the
effect and not relied on for self-filtering; ensure no unused variable warnings
remain (check the destructuring site in useWorkspaceRealtime and the interface
definition WorkspaceRealtimeOptions).

In `@src/lib/workspace/state-loader.ts`:
- Line 59: Define a concrete type for raw DB rows and replace the loose any[]
usages: create an interface (e.g., RawEventRow with fields eventId, eventType,
payload, timestamp, userId, userName, version) and change declarations like let
eventsData: any[] to let eventsData: RawEventRow[]; update other any-typed query
result variables in this file (the other occurrences around the mappings to
WorkspaceEvent) to use RawEventRow so the mapping logic (in functions/methods
that convert RawEventRow -> WorkspaceEvent) is strongly typed and safer to
maintain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ca343b6b-99ee-4b85-b780-b542e2cb1d67

📥 Commits

Reviewing files that changed from the base of the PR and between 30fbc0e and 2101112.

📒 Files selected for processing (10)
  • CLAUDE.md
  • public/.well-known/workflow/v1/manifest.json
  • src/app/api/workspaces/[id]/folders/route.ts
  • src/app/api/workspaces/[id]/import/route.ts
  • src/app/globals.css
  • src/components/layout/DashboardLayout.tsx
  • src/hooks/workspace/use-workspace-events.ts
  • src/hooks/workspace/use-workspace-realtime.ts
  • src/lib/workspace/state-loader.ts
  • src/workflows/ocr-dispatch/steps/persist-results.ts
💤 Files with no reviewable changes (1)
  • src/app/globals.css

@1shCha
Copy link
Copy Markdown
Contributor Author

1shCha commented Mar 30, 2026

@coderabbitai run

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 30, 2026

@1shCha Sure, I'll review the PR now!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@1shCha 1shCha merged commit 2101112 into main Mar 30, 2026
8 checks passed
@1shCha 1shCha deleted the main_chrome_ext_fix branch March 30, 2026 21:34
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Dev Board Mar 30, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant