-
Notifications
You must be signed in to change notification settings - Fork 2
Claude/add drive context tool gz gzm #185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
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
📝 WalkthroughWalkthroughRenames "AI Instructions" to "Drive Context" in the UI and state, extends drive creation to accept optional context, and adds a new authenticated Changes
Sequence DiagramsequenceDiagram
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
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this 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 insidegetDriveAccess()viagetDriveById(). Consider refactoringgetDriveAccess()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
📒 Files selected for processing (2)
apps/web/src/components/settings/DriveAISettings.tsxapps/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 useanytypes - 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 withuseprefix), Zustand stores (camelCase withuseprefix), and React components (PascalCase)
Lint with Next/ESLint as configured inapps/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/dbpackage for database access
Use ESM modules throughout the codebase
**/*.{ts,tsx}: Never useanytypes - always use proper TypeScript types
Write code that is explicit over implicit and self-documenting
Files:
apps/web/src/components/settings/DriveAISettings.tsxapps/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.tsxapps/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.tsxapps/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 withuseEditingStore.getState().startEditing()to prevent UI refreshes, and clean up in return statement
When AI is streaming, register streaming state withuseEditingStore.getState().startStreaming()to prevent UI refreshes, and clean up in return statement
For SWR data fetching with editing protection, useisPaused: () => hasLoadedRef.current && isEditingActive()to allow initial fetch and only pause after, withrevalidateOnFocus: false
Use Zustand for client-side state management as the primary state solution
Use SWR for server state and caching with proper configuration includingrevalidateOnFocus: falsefor 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 withuseprefix (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
getDriveAccessfrom@pagespace/lib/serverfollows the coding guidelines for using centralized permission functions. Database imports correctly use@pagespace/db.
120-161: Well-structured extension ofcreate_drivewith optional context.The implementation properly:
- Adds optional
contextparameter with 10K char limit via Zod schema- Renames destructured
contexttodriveContextto avoid shadowingexperimental_context- Persists to
drivePromptfield and returns relevant metadata
177-198: Clear response messaging for context handling.The conditional messaging and
nextStepsguidance provide good UX for AI consumers.
311-328: Good documentation and input schema forupdate_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
drivePromptfield with new context- Sets
updatedAttimestamp- Returns relevant fields for response
374-388: Good activity logging with context diff metadata.Logging both
previousValuesandnewValuesalong withupdateTypeandcontextLengthprovides 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, andnextSteps.apps/web/src/components/settings/DriveAISettings.tsx (4)
7-9: Icon change to Brain is semantically appropriate.The
Brainicon better represents "workspace memory/context" than the previousBoticon.
16-22: State variable renaming is consistent and clear.The rename from
drivePrompt/originalPrompttodriveContext/originalContextaligns 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_contexttool capability.
Check authorization via getDriveAccess first (which internally queries the drive), then only fetch drivePrompt field needed for logging.
There was a problem hiding this 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
drivestable:
getDriveAccess(line 338) internally queries the drive for authorization- A separate
select(lines 347-351) fetchesdrivePromptfor loggingWhile this separation is clear and the comment acknowledges the internal query, you could potentially optimize by having
getDriveAccessreturn 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
getDriveAccesscould 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
previousContextandcontextstrings (up to 10,000 characters each) inpreviousValuesandnewValues. 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
📒 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 useanytypes - 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 withuseprefix), Zustand stores (camelCase withuseprefix), and React components (PascalCase)
Lint with Next/ESLint as configured inapps/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/dbpackage for database access
Use ESM modules throughout the codebase
**/*.{ts,tsx}: Never useanytypes - 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 withuseprefix (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
getDriveAccessimport is properly added and follows the established import pattern from@pagespace/lib/server. This function is appropriately used for authorization checks in the newupdate_drive_contexttool.
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
drivePromptfrom the database but it's not exposed in the response object (onlyhasContext: !!driveContextis 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:
- First validates drive existence via
role === nullcheck- 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 includesdriveNamefor debugging context.
Summary by CodeRabbit
New Features
UI/UX Updates
✏️ Tip: You can customize this high-level summary in your review settings.