Skip to content

Conversation

@2witstudios
Copy link
Owner

@2witstudios 2witstudios commented Jan 13, 2026

Summary by CodeRabbit

  • New Features

    • Drive context can be provided at drive creation and updated later via a new "update drive context" action
    • Drive creation now surfaces whether context was included and reports context length in stats
  • UI/UX Updates

    • Renamed "AI Instructions" to "Drive Context" across settings and dialogs
    • Replaced Bot icon with Brain and updated related copy and examples

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

Add a new AI tool that allows the AI to update drive context (workspace
memory) as it learns about a project. This is similar to how CLAUDE.md
works in Claude Code - the AI can persist relevant information across
conversations.

Changes:
- Add update_drive_context tool to drive-tools.ts with proper permission
  checks (owners/admins only)
- Update create_drive tool to accept optional initial context parameter
- Update DriveAISettings UI from "AI Instructions" to "Drive Context"
  with updated description explaining the AI can also update it
- Change icon from Bot to Brain to better represent workspace memory
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

Renames "AI Instructions" to "Drive Context" in the UI and state, extends drive creation to accept optional context, and adds a new authenticated update_drive_context tool that validates access, updates stored context, broadcasts changes, and logs activity.

Changes

Cohort / File(s) Summary
UI Settings Component
apps/web/src/components/settings/DriveAISettings.tsx
Renamed internal state from drivePrompt/originalPromptdriveContext/originalContext; updated labels, placeholders, descriptions, icons (Bot→Brain), character counts, and save/patch mapping to use driveContext.
AI Tools & Drive Operations
apps/web/src/lib/ai/tools/drive-tools.ts
Extended create_drive input schema to accept optional context and persist it as drivePrompt (adds hasContext and contextLength stats); added new update_drive_context tool that performs authorization via getDriveAccess, validates drive, updates drives.drivePrompt, broadcasts real-time updates, and logs AI context activity; updated messages and nextSteps to reflect context.

Sequence Diagram

sequenceDiagram
    actor User
    participant Client as UI / Caller
    participant Tool as update_drive_context
    participant Auth as getDriveAccess
    participant DB as Database
    participant Broadcast as Real-time Broadcast
    participant Log as Activity Logger

    User->>Client: submit new context
    Client->>Tool: request update_drive_context(driveId, context)
    Tool->>Auth: validate access for driveId
    Auth->>DB: query drive ownership/permissions
    DB-->>Auth: return access decision
    alt access granted
        Auth-->>Tool: authorized
        Tool->>DB: update drives.drivePrompt with new context
        DB-->>Tool: update result
        Tool->>Broadcast: emit drive context update event
        Broadcast-->>Tool: confirm
        Tool->>Log: record AI context activity (prev/new)
        Log-->>Tool: recorded
        Tool-->>Client: success (updated drive info, stats)
        Client-->>User: show success
    else access denied
        Auth-->>Tool: unauthorized
        Tool-->>Client: error (permission denied)
        Client-->>User: show error
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Poem

🐰 I nibble on context, not prompts in the night,
Brain-icon glowing, the drive feels just right.
A patch, a broadcast, the memory grows bright,
Hopping with joy at each authorized write. 🧠✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 is unclear and contains noise (random suffixes 'gz gzm') that obscures the actual change, making it difficult to understand the PR's purpose at a glance. Revise the title to something clear like 'Add drive context tool for AI-managed workspace memory' to accurately reflect the main feature without extraneous characters.
✅ 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

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
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: 0

🧹 Nitpick comments (1)
apps/web/src/lib/ai/tools/drive-tools.ts (1)

335-349: Redundant drive query can be eliminated.

The code queries the drive twice: once with db.query.drives.findFirst() to verify it exists, then again inside getDriveAccess() via getDriveById(). Consider refactoring getDriveAccess() to return both the drive object and access info, allowing a single database query to serve both validation and authorization checks.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0125609 and 71c6ddf.

📒 Files selected for processing (2)
  • apps/web/src/components/settings/DriveAISettings.tsx
  • apps/web/src/lib/ai/tools/drive-tools.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Never use any types - always use proper TypeScript types
Use camelCase for variable and function names
Use UPPER_SNAKE_CASE for constants
Use PascalCase for type and enum names
Use kebab-case for filenames, except React hooks (camelCase with use prefix), Zustand stores (camelCase with use prefix), and React components (PascalCase)
Lint with Next/ESLint as configured in apps/web/eslint.config.mjs
Message content should always use the message parts structure with { parts: [{ type: 'text', text: '...' }] }
Use centralized permission functions from @pagespace/lib/permissions (e.g., getUserAccessLevel, canUserEditPage) instead of implementing permission logic locally
Always use Drizzle client from @pagespace/db package for database access
Use ESM modules throughout the codebase

**/*.{ts,tsx}: Never use any types - always use proper TypeScript types
Write code that is explicit over implicit and self-documenting

Files:

  • apps/web/src/components/settings/DriveAISettings.tsx
  • apps/web/src/lib/ai/tools/drive-tools.ts
**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/*.tsx: React component files should use PascalCase (e.g., UserProfile.tsx)
Use @dnd-kit for drag-and-drop functionality
Use Zustand for client state management
Use SWR for server state management and caching

Files:

  • apps/web/src/components/settings/DriveAISettings.tsx
**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Format code with Prettier

Files:

  • apps/web/src/components/settings/DriveAISettings.tsx
  • apps/web/src/lib/ai/tools/drive-tools.ts
**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Tailwind CSS and shadcn/ui components for styling and UI

Files:

  • apps/web/src/components/settings/DriveAISettings.tsx
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/web/src/**/*.{ts,tsx}: Use message parts structure for message content: { parts: [{ type: 'text', text: '...' }] }
For database access, always use Drizzle client from @pagespace/db: import { db, pages } from '@pagespace/db';
Use centralized Drizzle ORM with PostgreSQL for all database operations - no direct SQL or other ORMs
Use Socket.IO for real-time collaboration features - imported from the realtime service at port 3001
Use Vercel AI SDK with async/await for all AI operations and streaming
Use Next.js 15 App Router and TypeScript for all routes and components

Files:

  • apps/web/src/components/settings/DriveAISettings.tsx
  • apps/web/src/lib/ai/tools/drive-tools.ts
apps/web/src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/web/src/components/**/*.{ts,tsx}: When document editing, register editing state with useEditingStore.getState().startEditing() to prevent UI refreshes, and clean up in return statement
When AI is streaming, register streaming state with useEditingStore.getState().startStreaming() to prevent UI refreshes, and clean up in return statement
For SWR data fetching with editing protection, use isPaused: () => hasLoadedRef.current && isEditingActive() to allow initial fetch and only pause after, with revalidateOnFocus: false
Use Zustand for client-side state management as the primary state solution
Use SWR for server state and caching with proper configuration including revalidateOnFocus: false for editing protection
Use TipTap rich text editor with markdown support for document editing
Use Monaco Editor for code editing features
Use @dnd-kit for drag-and-drop functionality instead of other libraries
Use Tailwind CSS with shadcn/ui components for all UI styling and components

Files:

  • apps/web/src/components/settings/DriveAISettings.tsx
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: React hook files should use camelCase matching the exported hook name (e.g., useAuth.ts)
Zustand store files should use camelCase with use prefix (e.g., useAuthStore.ts)

Files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
🧠 Learnings (4)
📚 Learning: 2025-12-14T14:54:45.713Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:45.713Z
Learning: Applies to **/*.{ts,tsx} : Always use the Drizzle client and database exports from `pagespace/db` (e.g., `import { db, pages } from 'pagespace/db'`) for all database access

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
📚 Learning: 2025-12-23T18:49:41.966Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-23T18:49:41.966Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : For database access, always use Drizzle client from `pagespace/db`: `import { db, pages } from 'pagespace/db';`

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
📚 Learning: 2025-12-14T14:54:45.713Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:45.713Z
Learning: This is a monorepo using pnpm workspaces with structure: `apps/web` (Next.js frontend/backend), `apps/realtime` (Socket.IO service), `apps/processor` (Express file/OCR pipeline), `packages/db` (Drizzle ORM), `packages/lib` (shared utilities)

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
📚 Learning: 2025-12-22T20:04:40.910Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T20:04:40.910Z
Learning: Applies to **/*.{ts,tsx} : Always use Drizzle client from `pagespace/db` package for database access

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
🧬 Code graph analysis (1)
apps/web/src/components/settings/DriveAISettings.tsx (2)
apps/web/src/hooks/useToast.ts (1)
  • useToast (13-43)
apps/web/src/lib/auth/auth-fetch.ts (1)
  • fetchWithAuth (704-705)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Unit Tests
  • GitHub Check: Lint & TypeScript Check
🔇 Additional comments (11)
apps/web/src/lib/ai/tools/drive-tools.ts (7)

1-6: Imports look good.

The addition of getDriveAccess from @pagespace/lib/server follows the coding guidelines for using centralized permission functions. Database imports correctly use @pagespace/db.


120-161: Well-structured extension of create_drive with optional context.

The implementation properly:

  • Adds optional context parameter with 10K char limit via Zod schema
  • Renames destructured context to driveContext to avoid shadowing experimental_context
  • Persists to drivePrompt field and returns relevant metadata

177-198: Clear response messaging for context handling.

The conditional messaging and nextSteps guidance provide good UX for AI consumers.


311-328: Good documentation and input schema for update_drive_context.

The tool description clearly explains use cases, and the Zod schema enforces required fields with appropriate constraints.


351-365: Context update and database operation look correct.

The update operation properly:

  • Stores previous context for activity logging
  • Updates drivePrompt field with new context
  • Sets updatedAt timestamp
  • Returns relevant fields for response

374-388: Good activity logging with context diff metadata.

Logging both previousValues and newValues along with updateType and contextLength provides good auditability for AI-generated context changes.


390-412: Complete response structure with helpful next steps.

The response follows the established pattern from other tools with success, drive, message, summary, stats, and nextSteps.

apps/web/src/components/settings/DriveAISettings.tsx (4)

7-9: Icon change to Brain is semantically appropriate.

The Brain icon better represents "workspace memory/context" than the previous Bot icon.


16-22: State variable renaming is consistent and clear.

The rename from drivePrompt/originalPrompt to driveContext/originalContext aligns with the UI terminology change while maintaining the same logic.


47-66: API contract correctly preserved in save handler.

The PATCH request correctly uses drivePrompt (the database field name) while the UI uses "driveContext" terminology. This maintains backward compatibility with the API.


86-141: UI terminology consistently updated throughout.

Labels, descriptions, placeholders, and instructional text all use the new "Drive Context" terminology. The "How it works" section accurately describes the feature including the new update_drive_context tool capability.

Check authorization via getDriveAccess first (which internally queries
the drive), then only fetch drivePrompt field needed for logging.
Copy link
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: 0

🧹 Nitpick comments (2)
apps/web/src/lib/ai/tools/drive-tools.ts (2)

335-352: Consider consolidating the two drive queries for efficiency.

The code performs two separate queries to the drives table:

  1. getDriveAccess (line 338) internally queries the drive for authorization
  2. A separate select (lines 347-351) fetches drivePrompt for logging

While this separation is clear and the comment acknowledges the internal query, you could potentially optimize by having getDriveAccess return additional fields or by doing a single query that includes the context. However, this is a minor optimization and the current approach prioritizes separation of concerns.

♻️ Optional: Combine queries if getDriveAccess can be extended

If getDriveAccess could optionally return additional drive fields, you could eliminate the second query:

// If getDriveAccess could return drivePrompt when needed:
const access = await getDriveAccess(driveId, userId, { includeFields: ['drivePrompt'] });
const previousContext = access.drivePrompt || '';

Alternatively, keep as-is if query separation is preferred for maintainability.


375-389: Consider logging context hashes or truncated values instead of full text.

The activity log stores the complete previousContext and context strings (up to 10,000 characters each) in previousValues and newValues. For audit purposes, this could create very large log entries.

Consider logging truncated values or hashes if full-text audit isn't required:

 logDriveActivity(userId, 'update', {
   id: updatedDrive.id,
   name: updatedDrive.name,
 }, {
   ...aiContext,
-  previousValues: { drivePrompt: previousContext },
-  newValues: { drivePrompt: context },
+  previousValues: { drivePromptLength: previousContext.length },
+  newValues: { drivePromptLength: context.length },
   metadata: {
     ...aiContext.metadata,
     updateType: 'driveContext',
     contextLength: context.length,
+    previousContextLength: previousContext.length,
   },
 });

However, if full-text audit trails are a requirement, the current approach is correct.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71c6ddf and 648d764.

📒 Files selected for processing (1)
  • apps/web/src/lib/ai/tools/drive-tools.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Never use any types - always use proper TypeScript types
Use camelCase for variable and function names
Use UPPER_SNAKE_CASE for constants
Use PascalCase for type and enum names
Use kebab-case for filenames, except React hooks (camelCase with use prefix), Zustand stores (camelCase with use prefix), and React components (PascalCase)
Lint with Next/ESLint as configured in apps/web/eslint.config.mjs
Message content should always use the message parts structure with { parts: [{ type: 'text', text: '...' }] }
Use centralized permission functions from @pagespace/lib/permissions (e.g., getUserAccessLevel, canUserEditPage) instead of implementing permission logic locally
Always use Drizzle client from @pagespace/db package for database access
Use ESM modules throughout the codebase

**/*.{ts,tsx}: Never use any types - always use proper TypeScript types
Write code that is explicit over implicit and self-documenting

Files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ts: React hook files should use camelCase matching the exported hook name (e.g., useAuth.ts)
Zustand store files should use camelCase with use prefix (e.g., useAuthStore.ts)

Files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Format code with Prettier

Files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/web/src/**/*.{ts,tsx}: Use message parts structure for message content: { parts: [{ type: 'text', text: '...' }] }
For database access, always use Drizzle client from @pagespace/db: import { db, pages } from '@pagespace/db';
Use centralized Drizzle ORM with PostgreSQL for all database operations - no direct SQL or other ORMs
Use Socket.IO for real-time collaboration features - imported from the realtime service at port 3001
Use Vercel AI SDK with async/await for all AI operations and streaming
Use Next.js 15 App Router and TypeScript for all routes and components

Files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
🧠 Learnings (4)
📚 Learning: 2025-12-14T14:54:45.713Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:45.713Z
Learning: Applies to **/*.{ts,tsx} : Always use the Drizzle client and database exports from `pagespace/db` (e.g., `import { db, pages } from 'pagespace/db'`) for all database access

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
📚 Learning: 2025-12-23T18:49:41.966Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-23T18:49:41.966Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : For database access, always use Drizzle client from `pagespace/db`: `import { db, pages } from 'pagespace/db';`

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
📚 Learning: 2025-12-14T14:54:45.713Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:45.713Z
Learning: This is a monorepo using pnpm workspaces with structure: `apps/web` (Next.js frontend/backend), `apps/realtime` (Socket.IO service), `apps/processor` (Express file/OCR pipeline), `packages/db` (Drizzle ORM), `packages/lib` (shared utilities)

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
📚 Learning: 2025-12-22T20:04:40.910Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T20:04:40.910Z
Learning: Applies to **/*.{ts,tsx} : Always use Drizzle client from `pagespace/db` package for database access

Applied to files:

  • apps/web/src/lib/ai/tools/drive-tools.ts
🧬 Code graph analysis (1)
apps/web/src/lib/ai/tools/drive-tools.ts (6)
packages/db/src/index.ts (2)
  • db (20-20)
  • eq (8-8)
packages/db/src/schema/core.ts (1)
  • drives (7-22)
apps/web/src/lib/ai/core/types.ts (1)
  • ToolExecutionContext (8-37)
apps/web/src/lib/websocket/socket-utils.ts (2)
  • broadcastDriveEvent (140-172)
  • createDriveEventPayload (248-261)
packages/lib/src/monitoring/activity-logger.ts (1)
  • logDriveActivity (712-750)
apps/processor/src/logger.ts (1)
  • error (57-63)
🔇 Additional comments (4)
apps/web/src/lib/ai/tools/drive-tools.ts (4)

4-4: LGTM!

The getDriveAccess import is properly added and follows the established import pattern from @pagespace/lib/server. This function is appropriately used for authorization checks in the new update_drive_context tool.


120-205: Well-structured enhancement to support initial drive context.

The modifications are clean:

  • Good use of parameter aliasing (context: driveContext) to avoid shadowing the execution context
  • Proper validation with .max(10000) constraint
  • Context presence and length are appropriately surfaced in stats and messaging

One observation: Line 160 returns drivePrompt from the database but it's not exposed in the response object (only hasContext: !!driveContext is included). This is likely intentional to keep responses concise, but if the caller ever needs the actual context value, it won't be available.


338-344: LGTM!

The authorization flow is properly implemented:

  1. First validates drive existence via role === null check
  2. Then enforces owner/admin-only access with clear error messaging

This correctly handles all access scenarios including non-existent drives, viewers, and authorized users.


409-413: LGTM!

Error handling is consistent with the established pattern in other drive tools (e.g., rename_drive). The error message includes driveName for debugging context.

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.

3 participants