-
Notifications
You must be signed in to change notification settings - Fork 518
fix: Voucher sharing for claimants, sanitize large tool outputs, refactor drive file processing #1900
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: main
Are you sure you want to change the base?
Conversation
…and apply it to shared drive files.
… unified access and improved content normalization, and optimize file preview content handling.
WalkthroughAdds optional auth and unified public/private drive access with per-retrieval truncation and normalization; centralizes drive file placeholder replacement; propagates optional sanitization through action/tool-call DTOs and services; and introduces purePreview plus memoization improvements for file-preview renderers. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant DriveController
participant DriveService
participant PublicOSS as Public Storage (OSS)
participant PrivateStore as Private Storage
participant Sanitizer as Truncation/Sanitizer
Client->>DriveController: GET /drive/file/{id} (optional auth)
DriveController->>DriveService: getUnifiedFileMetadata(fileId, user?)
alt public metadata exists
DriveService->>PublicOSS: fetch metadata
PublicOSS-->>DriveService: metadata (isPublic: true)
else no public metadata
DriveService->>PrivateStore: validate ownership & fetch metadata
PrivateStore-->>DriveService: metadata (isPublic: false)
end
DriveController->>DriveService: getUnifiedFileStream(fileId, user?)
alt fetch from public
DriveService->>PublicOSS: stream content
PublicOSS-->>DriveService: data stream
else fetch from private
DriveService->>PrivateStore: stream content (owner validated)
PrivateStore-->>DriveService: data stream
end
DriveService->>Sanitizer: truncate/normalize and compute wordCount (if non-public or requested)
Sanitizer-->>DriveService: processed stream + metadata
DriveService-->>DriveController: stream + metadata (isPublic)
DriveController-->>Client: response (stream + metadata)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsx (1)
98-122: Addtto the dependency array for translation updates.The
useMemohook uses thetfunction fromuseTranslation(lines 102, 112) but has an empty dependency array. This prevents the segmented options from updating when the language changes, causing the labels to remain in the initial language until the page is reloaded.Recommended fix
value: 'code', }, ], - [], + [t], );packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx (1)
20-32: Shadow DOM content won't update whensanitizedSvgchanges.The guard
!el.shadowRootprevents re-attachment, but iffileContent.datachanges while the component remains mounted (e.g., previewing different files), the shadow DOM content won't update since the shadowRoot already exists.Consider updating the innerHTML when content changes:
🔎 Proposed fix
ref={(el) => { - if (el && !el.shadowRoot) { + if (el) { + let shadow = el.shadowRoot; + if (!shadow) { + shadow = el.attachShadow({ mode: 'open' }); + } - const shadow = el.attachShadow({ mode: 'open' }); // Inject styles to disable interactions on images and links shadow.innerHTML = ` <style> :host { display: block; } image, a { pointer-events: none; cursor: default; } </style> ${sanitizedSvg} `; } }}packages/web-core/src/pages/drive-file-share/index.tsx (1)
17-17: Remove debug console.log before merging.This debug statement should be removed from production code.
🔎 Proposed fix
- console.log('driveFileData', driveFileData);packages/agent-tools/src/builtin/index.ts (1)
417-430: Consider surfacing URL generation failures more prominently.The current error handling logs failures but silently falls back to the original content (lines 423-427, 460-463). This means users won't know their file references failed to resolve, resulting in broken
file://df-xxxorfile-content://df-xxxplaceholders in the generated document.Consider returning a partial success status or including a warning in the summary when some file URLs fail to generate, so users are aware of the issue.
💡 Suggested approach
Track failed replacements and include them in the result summary:
const urlResults = await Promise.all( uniqueFileIds.map(async (fileId) => { try { const { url, contentUrl } = await reflyService.createShareForDriveFile(user, fileId); return { fileId, shareUrl: url, contentUrl }; } catch (error) { console.error( `[BuiltinGenerateDoc] Failed to create share URL for fileId ${fileId}:`, error, ); return { fileId, shareUrl: null, contentUrl: null }; } }), ); + + // Track failed file IDs for user notification + const failedFileIds = urlResults + .filter(r => !r.shareUrl || !r.contentUrl) + .map(r => r.fileId);Then in the
_callmethod, append warning to summary if there are failures:summary: `Successfully generated document: "${input.title}" with ID: ${file.fileId}${ failedFileIds.length > 0 ? ` (Warning: ${failedFileIds.length} file reference(s) failed to resolve)` : '' }`Also applies to: 460-463
🧹 Nitpick comments (6)
apps/api/src/modules/action/action.dto.ts (1)
65-66: Clarify type safety ofoutput.datatype guard.Line 65 checks
typeof output.data === 'object'before type-asserting toRecord<string, unknown>on line 66. In JavaScript, both arrays and null satisfytypeof === 'object'. While the earlier checkoutput?.datarules out null, arrays would still pass this check. Consider adding an explicit array exclusion or clarifying that this is intentional:if ( toolName === 'read_file' && output?.data && typeof output.data === 'object' && !Array.isArray(output.data) ) {packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsx (1)
225-240: LGTM! Memoization comparison correctly extended.The additions of
canvasReadOnly,showActions, andpurePreviewto the comparison function are correct, as these props affect rendering behavior throughout the component.Minor note: The comment at line 227 could be slightly clearer. It currently says "to ensure state updates propagate," but the actual reason for not comparing
onTabChangeis to avoid unnecessary re-renders when the callback reference changes. State updates propagate through value props likeactiveTab, not through the callback comparison.Optional: Clarify the comment wording
- // Note: onTabChange is intentionally not compared to ensure state updates propagate + // Note: Callback props like onTabChange are not compared to prevent re-renders + // from reference changes. State updates propagate through value props like activeTab.packages/web-core/src/pages/drive-file-share/index.tsx (1)
49-53: Consider extracting HTML detection to a shared utility.This logic partially duplicates the backend's
isHtmlFilefunction indrive.utils.ts. If the backend supports additional HTML extensions (e.g.,.shtml,.xhtml), they won't triggerpurePreviewhere.Consider extracting this to a shared utility or ensuring consistency with the backend implementation.
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsx (1)
149-158: Pre-existing issue: Cleanup references potentially stalefileContent.The cleanup function references
fileContentbut it's not in the dependency array. WhenfetchFileContentchanges and cleanup runs, it may revoke the wrong URL or none at all.This is pre-existing behavior, but consider addressing it in a follow-up:
🔎 Suggested pattern using a ref
+ const fileContentUrlRef = useRef<string | null>(null); + useEffect(() => { fetchFileContent(); - // Cleanup object URL on unmount return () => { - if (fileContent?.url) { - URL.revokeObjectURL(fileContent.url); + if (fileContentUrlRef.current) { + URL.revokeObjectURL(fileContentUrlRef.current); } }; }, [fetchFileContent]); + + // Update ref when fileContent changes + useEffect(() => { + fileContentUrlRef.current = fileContent?.url ?? null; + }, [fileContent?.url]);packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsx (1)
15-41: Consider consolidating similar rendering blocks.The
purePreviewmode (lines 15-27) andcardmode (lines 30-41) have nearly identical rendering logic, differing only by thew-fullclass. This could be simplified to reduce duplication.🔎 Suggested consolidation
+ // Pure preview or card mode: render HTML directly + if (purePreview || source === 'card') { + return ( + <div className={`h-full overflow-hidden${purePreview ? ' w-full' : ''}`}> + <Renderer + content={textContent} + type="text/html" + title={file.name} + showActions={false} + purePreview={true} + /> + </div> + ); + } - // Pure preview mode: render HTML directly without CodeViewer chrome - if (purePreview) { - return ( - <div className="h-full w-full overflow-hidden"> - <Renderer - content={textContent} - type="text/html" - title={file.name} - showActions={false} - purePreview={true} - /> - </div> - ); - } - - // Card mode: simple preview - if (source === 'card') { - return ( - <div className="h-full overflow-hidden"> - <Renderer - content={textContent} - type="text/html" - title={file.name} - showActions={false} - purePreview={true} - /> - </div> - ); - }packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsx (1)
54-55: Extract duplicate voucher value calculation to a shared helper.The same calculation
Math.round((100 - discountPercent) / 10)appears in two places (line 55 and line 635). Extract this to a helper function to ensure consistency and improve maintainability.🔎 Proposed refactor
Add a helper function at the top of the file:
+// Convert discount percentage to Chinese "折" format +// e.g., 60% off -> 4折 (40% of original price) +const getVoucherValueInZhe = (discountPercent: number): number => { + return Math.round((100 - discountPercent) / 10); +}; + const gridSpan = {Then use it in both locations:
- const voucherValue = Math.round((100 - discountPercent) / 10); + const voucherValue = getVoucherValueInZhe(discountPercent);logEvent('voucher_applied', null, { - voucher_value: Math.round((100 - availableVoucher.discountPercent) / 10), + voucher_value: getVoucherValueInZhe(availableVoucher.discountPercent), entry_point: 'pricing_page',Also applies to: 635-635
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
apps/api/src/modules/action/action.dto.ts(1 hunks)apps/api/src/modules/drive/drive.controller.ts(4 hunks)apps/api/src/modules/drive/drive.service.ts(5 hunks)packages/agent-tools/src/builtin/index.ts(6 hunks)packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsx(3 hunks)packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsx(1 hunks)packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsx(3 hunks)packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsx(2 hunks)packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx(1 hunks)packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.ts(1 hunks)packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsx(2 hunks)packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsx(1 hunks)packages/web-core/src/pages/drive-file-share/index.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (22)
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{jsx,tsx}: Always use tailwind css to style the component
Always wrap pure components with React.memo to prevent unnecessary re-renders
Always use useMemo for expensive computations or complex object creation
Always use useCallback for function props to maintain referential equality
Always specify proper dependency arrays in useEffect to prevent infinite loops
Always avoid inline object/array creation in render to prevent unnecessary re-renders
Always use proper key props when rendering lists
Always split nested components with closures into separate components to avoid performance issues and improve code maintainability
**/*.{jsx,tsx}: Always wrap pure components with React.memo to prevent unnecessary re-renders
Always use useMemo for expensive computations or complex object creation in React
Always use useCallback for function props to maintain referential equality in React
Always specify proper dependency arrays in useEffect to prevent infinite loops in React
Always avoid inline object/array creation in render to prevent unnecessary re-renders in React
Always use proper key props when rendering lists in React (avoid using index when possible)
Always split nested components with closures into separate components in React
Use lazy loading for components that are not immediately needed in React
Debounce handlers for events that might fire rapidly (resize, scroll, input) in React
Implement fallback UI for components that might fail in React
Use error boundaries to catch and handle runtime errors in React
**/*.{jsx,tsx}: Place each attribute on a new line when a component has multiple attributes in JSX
Use self-closing tags for elements without children in JSX
Keep JSX expressions simple, extract complex logic to variables
Put closing brackets for multi-line JSX on a new line
**/*.{jsx,tsx}: Component file names should match the component name
Organize function components in order: imports, type definitions, constants, component function, hook calls, e...
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxpackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{jsx,tsx,css}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{jsx,tsx,css}: Use Tailwind CSS for styling components
Follow the utility-first approach with Tailwind CSS
Group related utility classes together in Tailwind CSS
Prefer Tailwind utilities over custom CSS when possible
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxpackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{jsx,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/05-code-organization.mdc)
Each component file should contain only one main component
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxpackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/05-code-organization.mdc)
Explicitly type props with interfaces or types in React components
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxpackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxapps/api/src/modules/action/action.dto.tspackages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxapps/api/src/modules/drive/drive.controller.tspackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxapps/api/src/modules/drive/drive.service.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
Use React best practices for frontend code
Files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxpackages/web-core/src/pages/drive-file-share/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
**/index.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/05-code-organization.mdc)
Use index files to export multiple components from a directory
Files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxpackages/agent-tools/src/builtin/index.tspackages/web-core/src/pages/drive-file-share/index.tsx
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/drive/drive.controller.tsapps/api/src/modules/drive/drive.service.ts
apps/api/src/**/*.controller.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Document APIs with OpenAPI specifications
Files:
apps/api/src/modules/drive/drive.controller.ts
🧠 Learnings (18)
📚 Learning: 2025-11-25T03:03:19.158Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/00-language-priority.mdc:0-0
Timestamp: 2025-11-25T03:03:19.158Z
Learning: Applies to **/{i18n,locales,translations,lang}/**/*.{json,ts,tsx,js,jsx,properties} : Use Chinese for all user-facing communication
Applied to files:
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsx
📚 Learning: 2025-11-25T03:02:45.779Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T03:02:45.779Z
Learning: Applies to **/*.{jsx,tsx} : Always wrap pure components with React.memo to prevent unnecessary re-renders
Applied to files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsxpackages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-25T03:04:41.334Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/09-i18n-guidelines.mdc:0-0
Timestamp: 2025-11-25T03:04:41.334Z
Learning: Applies to **/*.{tsx,ts,json} : Support dynamic content with placeholders in translations
Applied to files:
packages/agent-tools/src/builtin/index.tspackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsx
📚 Learning: 2025-11-25T03:05:07.580Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/11-ui-design-patterns.mdc:0-0
Timestamp: 2025-11-25T03:05:07.580Z
Learning: Applies to **/*.{tsx,ts,jsx,js,vue,css,scss,less} : Ensure proper spacing between card elements
Applied to files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsx
📚 Learning: 2025-11-25T03:05:07.580Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/11-ui-design-patterns.mdc:0-0
Timestamp: 2025-11-25T03:05:07.580Z
Learning: Applies to **/*.{tsx,ts,jsx,js,vue,css,scss,less} : Use subtle borders for card separation
Applied to files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsx
📚 Learning: 2025-11-25T03:02:45.779Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T03:02:45.779Z
Learning: Applies to **/*.{jsx,tsx} : Always use useMemo for expensive computations or complex object creation
Applied to files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-25T03:03:31.945Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/01-code-style.mdc:0-0
Timestamp: 2025-11-25T03:03:31.945Z
Learning: Applies to **/*.{jsx,tsx} : Always use useMemo for expensive computations or complex object creation in React
Applied to files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{controller,service}.ts : Use dependency injection for module dependencies in NestJS
Applied to files:
apps/api/src/modules/drive/drive.controller.ts
📚 Learning: 2025-11-25T03:04:51.017Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/10-testing-guidelines.mdc:0-0
Timestamp: 2025-11-25T03:04:51.017Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Test component rendering, interactions, prop handling, state changes, error states and edge cases in component tests
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsx
📚 Learning: 2025-11-25T03:02:45.779Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T03:02:45.779Z
Learning: Applies to **/*.{jsx,tsx} : Always use useCallback for function props to maintain referential equality
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-25T03:03:31.945Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/01-code-style.mdc:0-0
Timestamp: 2025-11-25T03:03:31.945Z
Learning: Applies to **/*.{jsx,tsx} : Always use useCallback for function props to maintain referential equality in React
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-26T05:04:26.523Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/08-contributing-guidelines.mdc:0-0
Timestamp: 2025-11-26T05:04:26.523Z
Learning: Applies to **/*.{tsx,jsx} : Use React best practices for frontend code
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-25T03:03:31.945Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/01-code-style.mdc:0-0
Timestamp: 2025-11-25T03:03:31.945Z
Learning: Applies to **/*.{jsx,tsx} : Always avoid inline object/array creation in render to prevent unnecessary re-renders in React
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-25T03:02:45.779Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T03:02:45.779Z
Learning: Applies to **/*.{jsx,tsx} : Always avoid inline object/array creation in render to prevent unnecessary re-renders
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx
📚 Learning: 2025-11-25T03:04:05.715Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/05-code-organization.mdc:0-0
Timestamp: 2025-11-25T03:04:05.715Z
Learning: Applies to **/*.{jsx,tsx} : Use ternary operators or && for conditional rendering in React
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsxpackages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsx
📚 Learning: 2025-11-25T03:04:05.715Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/05-code-organization.mdc:0-0
Timestamp: 2025-11-25T03:04:05.715Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Use functional updates for state (e.g., `setCount(prev => prev + 1)`)
Applied to files:
packages/ai-workspace-common/src/modules/artifacts/code-runner/code-viewer.tsx
📚 Learning: 2025-11-25T03:04:05.715Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/05-code-organization.mdc:0-0
Timestamp: 2025-11-25T03:04:05.715Z
Learning: Extract repeated JSX patterns into reusable components
Applied to files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsx
📚 Learning: 2025-11-25T03:03:31.945Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/01-code-style.mdc:0-0
Timestamp: 2025-11-25T03:03:31.945Z
Learning: Applies to **/*.{jsx,tsx} : Implement fallback UI for components that might fail in React
Applied to files:
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsx
🧬 Code graph analysis (5)
apps/api/src/modules/action/action.dto.ts (4)
packages/openapi-schema/src/types.gen.ts (1)
ToolCallResult(3445-3502)packages/ai-workspace-common/src/requests/types.gen.ts (1)
ToolCallResult(3396-3453)packages/request/src/requests/types.gen.ts (1)
ToolCallResult(3396-3453)apps/api/src/modules/tool/utils/token.ts (1)
safeParseJSON(371-377)
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsx (1)
apps/api/src/modules/drive/drive.service.ts (1)
truncateContent(627-641)
packages/web-core/src/pages/drive-file-share/index.tsx (2)
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsx (1)
FilePreview(86-267)apps/api/src/modules/drive/drive.utils.ts (1)
isHtmlFile(56-65)
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsx (2)
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.ts (1)
SourceRendererProps(16-23)packages/openapi-schema/src/types.gen.ts (1)
source(6261-6261)
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx (1)
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.ts (1)
FileRendererProps(10-13)
⏰ 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). (1)
- GitHub Check: build / Build
🔇 Additional comments (24)
apps/api/src/modules/action/action.dto.ts (2)
56-78: No actionable issue found.The
sanitizeToolOutputfunction receivestoolCall.toolNamefrom aToolCallResultModel(Prisma type), wheretoolNameis a requiredStringfield. The function signature correctly expects a non-optionalstringparameter. The optional nature oftoolNameapplies only to the OpenAPI return type, not the database input type.
80-98: Verify if sanitization of tool outputs impacts share page display.The modified
toolCallResultPO2DTOappliessanitizeToolOutputunconditionally to all tool results. Currently, forread_filetool outputs, thecontentfield is replaced with'[Content omitted for display]'before being returned.In
share-creation.service.ts, theactionResultPO2DTOfunction (which callstoolCallResultPO2DTOviaactionStepPO2DTO) is used to serialize action results for public share pages. Confirm that:
- Share pages do not require full file content from
read_fileoperations, or- An unsanitized data path is provided for share page generation to display full content as intended
All current callers of
toolCallResultPO2DTOreceive sanitized outputs with no option to bypass sanitization.packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/types.ts (1)
22-22: LGTM!The
purePreviewoptional prop is properly typed and follows the existing pattern for optional boolean properties in this interface.packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/svg.tsx (1)
6-14: LGTM! Good use of memoization.Moving the decode and sanitization into
useMemocorrectly avoids recomputation on every render. The dependency array properly includesfileContent.data. Based on learnings, this aligns with best practices for expensive computations in React.packages/web-core/src/pages/drive-file-share/index.tsx (1)
75-75: LGTM!The
purePreviewprop is correctly wired toisHtmlFile, enabling full HTML preview mode for HTML files on the share page.packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/index.tsx (1)
83-83: LGTM!The
purePreviewprop is properly typed, defaulted tofalse, and correctly forwarded toHtmlRenderer. This follows the existing pattern for optional props in this component.Also applies to: 92-92, 193-193
packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/markdown.tsx (2)
40-43: LGTM!Good refactor moving the decode and truncation into
useMemo. The dependency array correctly includes bothfileContent.dataanddisableTruncation. Based on learnings, this aligns with best practices for memoizing expensive computations.
54-57: LGTM!Consistent memoization pattern with the Card component. Both decode and truncation logic are properly memoized with correct dependencies.
apps/api/src/modules/drive/drive.controller.ts (4)
105-107: LGTM! Good implementation of optional authentication.The change from
JwtAuthGuardtoOptionalJwtAuthGuardcorrectly enables public file access while preserving private file authentication. TheUser | nulltype accurately reflects the optional nature of the authenticated user.
116-118: LGTM!The unified file metadata retrieval cleanly centralizes access control logic. The comment accurately describes the access check order (external/public first, then internal/private if authenticated).
139-145: LGTM! Correct conditional processing logic.The condition
user && !isPubliccorrectly ensures:
- Anonymous users don't trigger private URL processing
- Public files skip unnecessary processing regardless of auth status
- Only authenticated users accessing private files get content processing
16-16: OptionalJwtAuthGuard is correctly implemented.The guard properly validates tokens when present using
jwtService.verifyAsync()and gracefully allows null users when tokens are absent or invalid by settingrequest.user = nulland returningtrue. It supports token extraction from both Authorization headers and cookies, with appropriate error logging for invalid tokens.packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/code.tsx (3)
54-57: LGTM! Proper memoization of content decoding.Moving the
TextDecoderoperation insideuseMemocorrectly avoids repeated decoding on re-renders. The dependency array appropriately includes all values that affect the computation result.
106-109: LGTM! Consistent memoization pattern.The decoding and truncation are properly memoized. Since
MAX_PREVIEW_LINESandMAX_PREVIEW_CHARSare module-level constants, they don't need to be in the dependency array.
187-192: LGTM! Memoization correctly handles source-dependent truncation.Including
sourcein the dependency array is correct since it determines which truncation limits to apply.packages/ai-workspace-common/src/components/canvas/canvas-resources/file-preview/html.tsx (2)
1-12: LGTM! Good use of memoization for HTML content decoding.The
useMemocorrectly caches the decoded text content withfileContent.dataas the dependency. Based on learnings, this follows the guideline to always use useMemo for expensive computations.
45-62: LGTM! Preview mode with appropriate defaults.The nullish coalescing for
activeTab ?? 'preview'andonTabChange ?? (() => {})provides safe fallbacks. As per coding guidelines, this correctly uses nullish coalescing for potentially undefined values.apps/api/src/modules/drive/drive.service.ts (4)
606-615: LGTM! HR normalization enhancement.The regex patterns correctly normalize horizontal rules to standard markdown
---and deduplicate consecutive rules. The two-pass deduplication (before and after line trimming) handles edge cases.
659-664: Good approach: Re-apply truncation at retrieval time.This design allows
maxContentWordsconfiguration changes to take effect without re-parsing stored content. The comment accurately describes the behavior.
748-758: Verify wordCount reflects actual returned content.The
wordCountis calculated fromtruncatedContent(line 757) and stored in the cache (line 769). IfmaxContentWordsconfig changes later, the cachedwordCountwill be stale relative to newly truncated content returned at retrieval time. Is this acceptable for your use case, or shouldwordCountbe recalculated at retrieval?
1498-1584: LGTM! Unified file stream with proper error handling.The try-catch around
externalOss.getObjectcorrectly handles cases where the file doesn't exist in the public bucket, falling back to the internal OSS with authentication and ownership checks. The security logic properly prevents unauthorized access.packages/agent-tools/src/builtin/index.ts (2)
317-323: LGTM! Clear documentation for placeholder formats.The updated schema description provides clear guidance on the two supported placeholder formats with concrete examples. This will help the LLM understand when to use each format.
475-483: LGTM! Consistent documentation.The schema description is clear and consistent with the
generate_doctool's documentation.packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsx (1)
52-68: Locale-aware voucher display implementation looks good.The implementation correctly:
- Uses
i18n.languageto detect Chinese locale with safe optional chaining- Conditionally formats the discount text based on locale
- Maintains the memoized component structure to prevent unnecessary rerenders
- Falls back to English format with translation support for other locales
The logic is clean and follows React i18n best practices, subject to the precision concern raised separately.
packages/ai-workspace-common/src/components/settings/subscribe-modal/priceContent.tsx
Show resolved
Hide resolved
…result display sanitization, and configure Serena project settings.
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: 2
🧹 Nitpick comments (3)
apps/api/src/modules/voucher/voucher.service.ts (2)
648-660: Consider extracting the permission check into a reusable helper method.The permission check logic (owner OR claimant) is duplicated between this method and
validateVoucher(lines 527-534). This violates the DRY principle and increases maintenance burden.🔎 Suggested refactor to eliminate duplication
Add a private helper method:
/** * Check if user has permission to access/use a voucher (owner or claimant) */ private async checkVoucherPermission( uid: string, voucherId: string ): Promise<boolean> { const voucher = await this.prisma.voucher.findFirst({ where: { voucherId }, }); if (!voucher) { return false; } // Check if user is owner const isOwner = voucher.uid === uid; if (isOwner) { return true; } // Check if user is claimant const isClaimant = await this.prisma.voucherInvitation.findFirst({ where: { voucherId, inviteeUid: uid, status: InvitationStatus.CLAIMED, }, }); return !!isClaimant; }Then simplify
createInvitation:async createInvitation(uid: string, voucherId: string): Promise<CreateInvitationResult> { - // Get the voucher (without uid filter - we'll check permission separately) - const voucher = await this.prisma.voucher.findFirst({ - where: { voucherId }, - }); - - if (!voucher) { - throw new Error('Voucher not found'); - } - - // Check permission: owner OR claimant (same logic as validateVoucher) - const isOwner = voucher.uid === uid; - const isClaimant = await this.prisma.voucherInvitation.findFirst({ - where: { - voucherId, - inviteeUid: uid, - status: InvitationStatus.CLAIMED, - }, - }); - - if (!isOwner && !isClaimant) { + const hasPermission = await this.checkVoucherPermission(uid, voucherId); + if (!hasPermission) { throw new Error('Voucher not found'); } + + const voucher = await this.prisma.voucher.findFirst({ + where: { voucherId }, + });You can apply the same refactor to
validateVoucher.
658-660: Add logging for permission denial attempts.When permission is denied (line 659), consider logging this event for security monitoring and debugging purposes. This can help identify potential abuse attempts or misconfigurations.
🔎 Suggested logging addition
if (!isOwner && !isClaimant) { + this.logger.warn( + `Permission denied: User ${uid} attempted to create invitation for voucher ${voucherId}` + ); throw new Error('Voucher not found'); }apps/api/src/modules/action/action.dto.ts (1)
62-80: Strengthen the type guard foroutput.data.The current type check
typeof output.data === 'object'will pass for arrays and (without the optional chaining) would pass fornull. Consider a more explicit check to ensuredatais a plain object:🔎 Proposed refinement
export function sanitizeToolOutput( toolName: string, output: Record<string, unknown>, ): Record<string, unknown> { // For read_file, remove the content field from data as it can be very large - if (toolName === 'read_file' && output?.data && typeof output.data === 'object') { + if ( + toolName === 'read_file' && + output?.data && + typeof output.data === 'object' && + !Array.isArray(output.data) && + output.data !== null + ) { const data = output.data as Record<string, unknown>; if ('content' in data) { return { ...output, data: { ...data, content: '[Content omitted for display]', }, }; } } return output; }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/api/src/modules/action/action.controller.ts(1 hunks)apps/api/src/modules/action/action.dto.ts(4 hunks)apps/api/src/modules/action/action.service.ts(7 hunks)apps/api/src/modules/copilot/copilot.dto.ts(1 hunks)apps/api/src/modules/voucher/voucher.constants.ts(1 hunks)apps/api/src/modules/voucher/voucher.service.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.service.ts
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
apps/api/src/modules/voucher/voucher.service.tsapps/api/src/modules/action/action.controller.tsapps/api/src/modules/action/action.dto.tsapps/api/src/modules/voucher/voucher.constants.tsapps/api/src/modules/copilot/copilot.dto.tsapps/api/src/modules/action/action.service.ts
apps/api/src/**/*.controller.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Document APIs with OpenAPI specifications
Files:
apps/api/src/modules/action/action.controller.ts
🧬 Code graph analysis (3)
apps/api/src/modules/voucher/voucher.service.ts (4)
packages/openapi-schema/src/types.gen.ts (2)
CreateInvitationResult(9312-9317)InvitationStatus(9175-9175)apps/api/src/modules/voucher/voucher.dto.ts (1)
CreateInvitationResult(89-91)packages/ai-workspace-common/src/requests/types.gen.ts (2)
CreateInvitationResult(9251-9264)InvitationStatus(9114-9114)apps/api/src/modules/voucher/voucher.constants.ts (1)
InvitationStatus(42-46)
apps/api/src/modules/action/action.controller.ts (2)
apps/api/src/utils/response.ts (1)
buildSuccessResponse(48-53)apps/api/src/modules/action/action.dto.ts (1)
actionResultPO2DTO(107-143)
apps/api/src/modules/copilot/copilot.dto.ts (1)
apps/api/src/modules/action/action.dto.ts (1)
actionResultPO2DTO(107-143)
⏰ 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). (1)
- GitHub Check: build / Build
🔇 Additional comments (5)
apps/api/src/modules/voucher/voucher.service.ts (1)
638-683: Permission model looks correct and consistent.The changes correctly implement the new permission model where both the voucher owner and claimants can create invitations. The logic mirrors the permission checks in
validateVoucher(lines 527-534), ensuring consistency across the service.The intentional use of a generic "Voucher not found" error message (line 659) for permission denial is appropriate for security, preventing enumeration of valid voucher IDs.
apps/api/src/modules/voucher/voucher.constants.ts (1)
6-6: Confirm the purpose of the daily popup trigger limit value.The
DAILY_POPUP_TRIGGER_LIMITconstant is set to 999 and is actively used in thecheckDailyTriggerLimit()method (line 316) to control how many times a user can trigger the voucher popup per day. A limit of 999 is unusually high and effectively removes any practical daily restriction. This change appears unrelated to the stated PR objectives (file preview truncation and canvas duplication fixes).Clarify whether this high limit is intentional, and if so, provide justification for its inclusion in this PR.
apps/api/src/modules/action/action.controller.ts (1)
20-24: LGTM! Sanitization is consistently applied.The controller correctly passes
sanitizeForDisplay: trueto both the service call and the DTO mapper, ensuring large outputs are redacted for display purposes throughout the response pipeline.apps/api/src/modules/action/action.service.ts (2)
78-80: Sanitization propagation is correctly implemented.The service properly forwards the
sanitizeForDisplayoption through the enrichment pipeline and conditionally appliessanitizeToolOutputto tool call results. The integration with the DTO layer ensures consistent sanitization across the response structure.Also applies to: 98-154
138-144: Clarify inconsistent fallback handling for malformed tool output.The code creates a
{ rawOutput: ... }wrapper whensafeParseJSONfails, buttoolCallResultPO2DTOin action.dto.ts handles the same conversion without this fallback. This creates structural inconsistency: parsed outputs have their original structure, while malformed JSON gets wrapped differently. ThesanitizeToolOutputfunction may not handle this wrapped structure correctly (e.g., won't find thedatafield forread_filesanitization). Either remove the fallback for consistency with action.dto.ts, or document why it's necessary and ensure downstream consumers handle both structures.
… size estimation, and include Serena project configuration.
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 (5)
apps/api/src/modules/tool-call/tool-call.service.ts (2)
238-242: Consider adding JSDoc for the new parameter.The method signature update is correct and backward-compatible. However, the existing JSDoc comment (lines 227-237) doesn't document the new
optionsparameter.📝 Suggested JSDoc update
Update the JSDoc comment to include:
* Attach tool calls to steps and merge XML content * This method combines grouping and content merging in one operation: * 1. Groups tool calls by step name (with fallback to last step) * 2. Generates XML content for each tool call * 3. Merges XML content into step.content * * @param steps - Array of steps with name and optional content * @param toolCalls - Array of tool calls with optional stepName + * @param options - Optional configuration + * @param options.sanitizeForDisplay - When true, sanitizes tool outputs (e.g., omits large content fields) * @returns Steps with attached tool calls and merged XML content
274-280: Verify type safety withsanitizeToolOutput.The code passes
rawOutput(typed asanyfromsafeParseJSON) and potentially undefinedcall.toolNametosanitizeToolOutput, which expectsRecord<string, unknown>andstringrespectively.While the current implementation is safe because:
sanitizeToolOutputonly checkstoolName === 'read_file', so undefined falls through harmlessly- The function handles non-matching types gracefully
Consider adding explicit type guards or using optional chaining to make the type safety more explicit and prevent future issues if
sanitizeToolOutputis enhanced.🔎 Suggested type-safe approach
// Parse output JSON string and optionally sanitize const rawOutput = safeParseJSON(call.output || '{}') ?? {}; const output = options?.sanitizeForDisplay - ? sanitizeToolOutput(call.toolName, rawOutput) + ? sanitizeToolOutput(call.toolName ?? '', rawOutput as Record<string, unknown>) : rawOutput;apps/api/src/modules/action/action.service.ts (3)
95-99: Consider documenting the new parameter.The method signature update is correct. However, consider adding a JSDoc comment block (if not already present) or updating existing documentation to describe the
optionsparameter and itssanitizeForDisplayflag.
138-145: Inconsistent fallback logic compared to tool-call.service.ts.In this file, when
safeParseJSONreturnsnull, the fallback wraps the raw output:const rawOutput = safeParseJSON(toolCallResult.output || '{}') ?? { rawOutput: toolCallResult.output, };However, in
tool-call.service.ts(line 276), the fallback is simply{}:const rawOutput = safeParseJSON(call.output || '{}') ?? {};This inconsistency could lead to different behavior in edge cases where JSON parsing fails. Consider aligning the fallback strategy across both files for consistency.
🔎 Suggested alignment
Option 1: Use simple empty object (matches tool-call.service.ts):
-const rawOutput = safeParseJSON(toolCallResult.output || '{}') ?? { - rawOutput: toolCallResult.output, -}; +const rawOutput = safeParseJSON(toolCallResult.output || '{}') ?? {};Option 2: Use wrapped fallback in both places (if the wrapping serves a purpose):
Update tool-call.service.ts line 276 to match this pattern.
138-145: Verify type safety withsanitizeToolOutput.Similar to the issue in
tool-call.service.ts, this code passesrawOutput(typed asany) and potentially undefinedtoolCallResult.toolNametosanitizeToolOutput. While safe in the current implementation, explicit type handling would improve code clarity and prevent future issues.🔎 Suggested type-safe approach
const rawOutput = safeParseJSON(toolCallResult.output || '{}') ?? { rawOutput: toolCallResult.output, }; // Apply sanitization if needed const output = options?.sanitizeForDisplay - ? sanitizeToolOutput(toolCallResult.toolName, rawOutput) + ? sanitizeToolOutput(toolCallResult.toolName ?? '', rawOutput as Record<string, unknown>) : rawOutput;
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/api/src/modules/action/action.service.ts(8 hunks)apps/api/src/modules/tool-call/tool-call.service.ts(4 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
apps/api/src/modules/action/action.service.tsapps/api/src/modules/tool-call/tool-call.service.ts
🧬 Code graph analysis (2)
apps/api/src/modules/action/action.service.ts (2)
apps/api/src/modules/tool/utils/token.ts (1)
safeParseJSON(371-377)apps/api/src/modules/action/action.dto.ts (1)
sanitizeToolOutput(62-80)
apps/api/src/modules/tool-call/tool-call.service.ts (4)
packages/openapi-schema/src/types.gen.ts (2)
ActionStep(1709-1744)ToolCallResult(3445-3502)packages/request/src/requests/types.gen.ts (2)
ActionStep(1668-1703)ToolCallResult(3396-3453)apps/api/src/modules/tool/utils/token.ts (1)
safeParseJSON(371-377)apps/api/src/modules/action/action.dto.ts (1)
sanitizeToolOutput(62-80)
⏰ 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). (1)
- GitHub Check: build / Build
🔇 Additional comments (6)
apps/api/src/modules/tool-call/tool-call.service.ts (1)
5-5: LGTM!The imports for
safeParseJSONandsanitizeToolOutputare properly added to support the new sanitization functionality.Also applies to: 9-9
apps/api/src/modules/action/action.service.ts (5)
25-25: LGTM!The import of
sanitizeToolOutputis correctly added to support the sanitization feature.
36-39: LGTM!The addition of
sanitizeForDisplaytoGetActionResultParamsproperly extends the type to support optional sanitization control.
64-64: LGTM!The destructuring with a default value of
falseensures backward compatibility and follows best practices for optional parameters.
78-80: LGTM!The
sanitizeForDisplayoption is correctly propagated to the enrichment method.
171-173: LGTM!The
sanitizeForDisplayoption is correctly propagated toattachToolCallsToSteps, completing the sanitization pipeline.
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: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/api/src/modules/drive/drive.service.ts (1)
627-641: Critical bug:truncateContentremoves all spaces between words.Lines 637-638 join words with an empty string (
join('')), which concatenates words without any separator. This removes all spaces between words in both the head and tail sections of truncated content, making it unreadable.Since this method is called by the newly added truncation logic (lines 664, 754), this bug will corrupt all truncated content returned to users.
🔎 Proposed fix
- const head = words.slice(0, headWords).join(''); - const tail = words.slice(-tailWords).join(''); + const head = words.slice(0, headWords).join(' '); + const tail = words.slice(-tailWords).join(' ');
♻️ Duplicate comments (3)
packages/agent-tools/src/builtin/index.ts (3)
526-617: Extract duplicated replaceFilePlaceholders + fix critical regex bugs.This method is almost identical to
BuiltinGenerateDoc.replaceFilePlaceholders(lines 356-441), violating DRY principles. Additionally, it contains the same critical regex bugs:
- Line 539:
hasFile = content.includes('file://df-')incorrectly matchesfile-content://URLs- Line 548: Pattern lacks negative lookbehind to exclude
file-content://prefix- Line 608: Replacement pattern will corrupt
file-content://URLsImpact: Code duplication creates maintenance burden (bug fixes must be applied in multiple places), and the regex bugs cause content corruption.
🔎 Recommended refactoring + fix
Extract the common logic to a shared module-level helper:
/** * Replace file placeholders in content with HTTP URLs. * Supported formats: * - `file-content://df-xxx` → Direct file content URL (for images, embedded media) * - `file://df-xxx` → Share page URL (for links) */ async function replaceFilePlaceholders( content: string, reflyService: ReflyService, user: User, logContext: string, ): Promise<string> { if (!content) { return content; } const hasFileContent = content.includes('file-content://df-'); const hasFile = /(?<!file-content:)\/\/df-/.test(content); if (!hasFileContent && !hasFile) { return content; } try { const contentMatchPattern = /file-content:\/\/(df-[a-z0-9]+)/gi; const shareMatchPattern = /(?<!file-content:)file:\/\/(df-[a-z0-9]+)/gi; const contentMatches = Array.from(content.matchAll(contentMatchPattern)); const shareMatches = Array.from(content.matchAll(shareMatchPattern)); const allFileIds = new Set<string>(); for (const [, fileId] of contentMatches) { allFileIds.add(fileId); } for (const [, fileId] of shareMatches) { allFileIds.add(fileId); } if (allFileIds.size === 0) { return content; } const uniqueFileIds = Array.from(allFileIds); const urlResults = await Promise.all( uniqueFileIds.map(async (fileId) => { try { const { url, contentUrl } = await reflyService.createShareForDriveFile(user, fileId); return { fileId, shareUrl: url, contentUrl }; } catch (error) { console.error(`[${logContext}] Failed to create share URL for ${fileId}:`, error); return { fileId, shareUrl: null, contentUrl: null }; } }), ); const shareUrlMap = new Map<string, string>(); const contentUrlMap = new Map<string, string>(); for (const { fileId, shareUrl, contentUrl } of urlResults) { if (shareUrl) { shareUrlMap.set(fileId, shareUrl); } if (contentUrl) { contentUrlMap.set(fileId, contentUrl); } } let result = content; result = result.replace( /file-content:\/\/(df-[a-z0-9]+)/gi, (match, fileId: string) => contentUrlMap.get(fileId) ?? match, ); result = result.replace( /(?<!file-content:)file:\/\/(df-[a-z0-9]+)/gi, (match, fileId: string) => shareUrlMap.get(fileId) ?? match, ); return result; } catch (error) { console.error(`[${logContext}] Error replacing file placeholders:`, error); return content; } }Then update both classes:
// In BuiltinGenerateDoc private async replaceFilePlaceholders(content: string): Promise<string> { const { reflyService, user } = this.params; return replaceFilePlaceholders(content, reflyService, user, 'BuiltinGenerateDoc'); } // In BuiltinGenerateCodeArtifact private async replaceFilePlaceholders(content: string): Promise<string> { const { reflyService, user } = this.params; return replaceFilePlaceholders(content, reflyService, user, 'BuiltinGenerateCodeArtifact'); }Note:
BuiltinSendEmailhas slightly different logic (callsreadFilefirst), so it may need separate handling or optional parameters.As per past review comments on lines 526-617 and 361-464.
706-706: Same critical regex bug in BuiltinSendEmail.Lines 706 and 767 use patterns without negative lookbehinds, causing the same content corruption issue:
- Line 706: Pattern will match
file://df-xxxinsidefile-content://df-xxx- Line 767: Replacement will corrupt
file-content://URLs🔎 Proposed fix
// Match both formats: file-content://df-xxx and file://df-xxx const contentMatchPattern = /file-content:\/\/(df-[a-zA-Z0-9]+)/g; - const shareMatchPattern = /file:\/\/(df-[a-zA-Z0-9]+)/g; + const shareMatchPattern = /(?<!file-content:)file:\/\/(df-[a-zA-Z0-9]+)/g;And:
// Replace file:// with share page URLs (but not file-content://) result = result.replace( - /file:\/\/(df-[a-zA-Z0-9]+)/g, + /(?<!file-content:)file:\/\/(df-[a-zA-Z0-9]+)/g, (match, fileId: string) => shareUrlMap.get(fileId) ?? match, );As per past review comments.
Also applies to: 767-767
432-434: Same regex bug at replacement stage.Line 432 uses the same pattern without negative lookbehind, causing actual content corruption during replacement. This will replace
file://df-xxxinsidefile-content://df-xxxURLs with share URLs, breaking the content URLs.Apply the same fix as suggested for line 372:
// Replace file://df-xxx with share page URLs (but not file-content://) result = result.replace( - /file:\/\/(df-[a-z0-9]+)/gi, + /(?<!file-content:)file:\/\/(df-[a-z0-9]+)/gi, (match, fileId: string) => shareUrlMap.get(fileId) ?? match, );
🧹 Nitpick comments (2)
apps/api/src/modules/drive/drive.service.ts (2)
1452-1474: Consider consistent error handling across unified methods.Lines 1454-1458 log all
externalOss.statObjecterrors at debug level without checking error codes. However,getUnifiedFileStream(lines 1556-1562) filters errors and logs warnings only for errors that are NOT "not found" errors.For consistency and better diagnostics, consider applying the same error filtering pattern here: log expected "not found" errors at debug level and unexpected errors at warn level.
🔎 Proposed refinement for consistency
// Step 1: Check if file exists in externalOss (public) let externalObjectInfo: Awaited<ReturnType<typeof this.externalOss.statObject>> | null = null; try { externalObjectInfo = await this.externalOss.statObject(storageKey); } catch (error) { - this.logger.debug(`External OSS stat failed for ${storageKey}: ${error.message}`); + // Log only unexpected errors; "not found" is expected and handled below + if ( + error?.code !== 'NoSuchKey' && + error?.code !== 'NotFound' && + !error?.message?.includes('The specified key does not exist') + ) { + this.logger.warn(`Error checking externalOss for ${fileId}: ${error.message}`); + } }
606-607: Optional: horizontal rule regex accepts mixed characters.Line 607's regex
[-_=]{4,}matches 4+ of any combination of dashes, underscores, or equals, including mixed patterns like--__or-_-_. Standard markdown horizontal rules use the same character repeated (---,___, or***).If strict markdown compliance is desired, consider restricting to same-character sequences. Otherwise, this is acceptable as a more permissive normalization.
🔎 Alternative regex for strict markdown compliance
// Normalize excessive horizontal rules (4+ dashes/underscores/equals) to standard markdown hr - .replace(/^[ \t]*[-_=]{4,}[ \t]*$/gm, '---') + .replace(/^[ \t]*(-{4,}|_{4,}|={4,})[ \t]*$/gm, '---')This ensures each horizontal rule uses only one type of character.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/api/src/modules/drive/drive.service.ts(5 hunks)packages/agent-tools/src/builtin/index.ts(9 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/drive/drive.service.ts
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
apps/api/src/modules/drive/drive.service.tspackages/agent-tools/src/builtin/index.ts
**/index.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/05-code-organization.mdc)
Use index files to export multiple components from a directory
Files:
packages/agent-tools/src/builtin/index.ts
🧠 Learnings (3)
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/**/*.{controller,service}.ts : Implement proper error handling in API modules
Applied to files:
apps/api/src/modules/drive/drive.service.ts
📚 Learning: 2025-11-25T03:04:41.334Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/09-i18n-guidelines.mdc:0-0
Timestamp: 2025-11-25T03:04:41.334Z
Learning: Applies to **/*.{tsx,ts,json} : Support dynamic content with placeholders in translations
Applied to files:
packages/agent-tools/src/builtin/index.ts
📚 Learning: 2025-11-26T05:04:26.523Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/08-contributing-guidelines.mdc:0-0
Timestamp: 2025-11-26T05:04:26.523Z
Learning: Applies to **/*.{md,mdx} : Update documentation if needed
Applied to files:
packages/agent-tools/src/builtin/index.ts
🧬 Code graph analysis (1)
apps/api/src/modules/drive/drive.service.ts (2)
packages/openapi-schema/src/types.gen.ts (1)
User(474-483)packages/utils/src/file.ts (1)
getSafeMimeType(90-109)
⏰ 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). (1)
- GitHub Check: build / Build
🔇 Additional comments (5)
packages/agent-tools/src/builtin/index.ts (3)
294-300: LGTM! Clear documentation for placeholder formats.The updated schema description clearly distinguishes between
file-content://andfile://placeholder formats with practical examples.
452-460: LGTM! Clear documentation improvements.The updated schema descriptions and SVG notes provide clear guidance on placeholder usage and technical requirements for SVG elements.
Also applies to: 479-480
361-388: Critical regex bug: Pattern matches inside file-content:// URLs.Lines 363 and 372 have critical correctness issues:
- Line 363:
content.includes('file://df-')returns true forfile-content://df-xxxbecause it contains the substringfile://df-.- Line 372: Pattern
/file:\/\/(df-[a-z0-9]+)/gimatchesfile://df-xxxinsidefile-content://df-xxxstrings.Impact: Content like
<img src="file-content://df-abc123">will be incorrectly parsed, extractingdf-abc123as a share URL candidate and corrupting the replacement at line 432.This issue was flagged in past review comments, which suggested using a negative lookbehind. The current changes removed the lookbehind entirely, making the problem worse.
🔎 Proposed fix using negative lookbehind
// Check for placeholder formats const hasFileContent = content.includes('file-content://df-'); - const hasFile = content.includes('file://df-'); + const hasFile = /(?<!file-content:)\/\/df-/.test(content); if (!hasFileContent && !hasFile) { return content; } try { // Match both formats const contentMatchPattern = /file-content:\/\/(df-[a-z0-9]+)/gi; - const shareMatchPattern = /file:\/\/(df-[a-z0-9]+)/gi; + const shareMatchPattern = /(?<!file-content:)file:\/\/(df-[a-z0-9]+)/gi;Likely an incorrect or invalid review comment.
apps/api/src/modules/drive/drive.service.ts (2)
748-750: Verify type compatibility:putObjectexpects Buffer.Line 750 passes
processedContent(a string) toputObject, but other calls in this file (e.g., line 475) pass a Buffer. Verify that the OSS service handles automatic string-to-Buffer conversion, or convert explicitly.Based on coding guidelines, ensure type consistency across OSS operations.
🔎 Suggested fix if conversion is needed
// Store normalized content to OSS (without truncation, so we can adjust limits later) const contentStorageKey = `drive-parsed/${user.uid}/${fileId}.txt`; - await this.internalOss.putObject(contentStorageKey, processedContent); + await this.internalOss.putObject(contentStorageKey, Buffer.from(processedContent, 'utf-8'));
1503-1589: Well-structured unified file access with proper ownership validation.The implementation correctly handles the public-first, then private-with-ownership access pattern:
- Attempts public access from externalOss without auth requirements
- Falls back to private access with user ownership validation
- Distinguishes "not found" errors from other errors (lines 1556-1562)
- Returns
isPublicflag for downstream handlingThis provides a clean abstraction for unified file access across public and private buckets.
| // Calculate word count from truncated content | ||
| const wordCount = readingTime(truncatedContent).words; |
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.
Clarify intent: word count calculated from truncated content.
Line 757 calculates wordCount from the truncated content rather than the full processedContent. This means the cached wordCount represents the truncated version's length, not the full document's length.
If the intent is to track the full document's word count for usage metrics or display purposes, this should use processedContent instead. If truncated count is intentional, consider adding a comment explaining why.
🔎 Proposed fix if full document count is needed
// Truncate content for return (but not for storage)
const maxWords = this.config.get<number>('drive.maxContentWords') || 3000;
const truncatedContent = this.truncateContent(processedContent, maxWords);
- // Calculate word count from truncated content
- const wordCount = readingTime(truncatedContent).words;
+ // Calculate word count from full content for accurate document metrics
+ const wordCount = readingTime(processedContent).words;🤖 Prompt for AI Agents
In apps/api/src/modules/drive/drive.service.ts around lines 756-757, the code
computes wordCount from truncatedContent which causes the cached word count to
reflect the truncated snippet rather than the full processedContent; if the
intent is to measure the full document change the call to use processedContent
(i.e., wordCount = readingTime(processedContent).words) and ensure any
cached/returned metadata uses that value, otherwise add a brief inline comment
clarifying that using truncatedContent is intentional and why (e.g., for
preview-based metrics) so future readers aren’t confused.
Summary
Fix voucher sharing permission, sanitize large tool outputs, and refactor drive file processing.
Voucher Service:
validateVoucherlogicTool Output Sanitization:
readFileandlistFileswith content truncationDrive File Processing:
drive.service.tsfor unified file access and improved content normalizationdisableTruncationprop to file preview components for shared drive filesCleanup:
Impact Areas
Checklist
dev/reformat(backend) andcd web && npx lint-staged(frontend) to appease the lint godsSummary by CodeRabbit
New Features
Behavior Changes
Performance
✏️ Tip: You can customize this high-level summary in your review settings.