Skip to content

Conversation

@alchemistklk
Copy link
Contributor

@alchemistklk alchemistklk commented Dec 8, 2025

…contention

Summary

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Tip

Close issue syntax: Fixes #<issue number> or Resolves #<issue number>, see documentation for more details.

Impact Areas

Please check the areas this PR affects:

  • Multi-threaded Dialogues
  • AI-Powered Capabilities (Web Search, Knowledge Base Search, Question Recommendations)
  • Context Memory & References
  • Knowledge Base Integration & RAG
  • Quotes & Citations
  • AI Document Editing & WYSIWYG
  • Free-form Canvas Interface
  • Other

Screenshots/Videos

Before After
... ...

Checklist

Important

Please review the checklist below before submitting your pull request.

  • This change requires a documentation update, included: Refly Documentation
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran dev/reformat(backend) and cd web && npx lint-staged(frontend) to appease the lint gods

Summary by CodeRabbit

  • Refactor
    • Switched to batched processing for output resources to improve throughput, error handling, and mapping of created file references.
  • Bug Fixes
    • Normalized tool result formatting with robust handling of API errors and double-escaped JSON.
    • Ensure tool error and completion events consistently present parsed JSON when possible.
  • New Features
    • Added flexible billing configuration for tools, accepting simple credit values or full billing settings.

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds batched output-resource processing to the tool resource service, centralizes raw-result extraction and JSON-normalization in the markdown tool-call renderer, extends inventory billing parsing to accept BillingConfig objects, and normalizes tool output parsing on tool error/end events.

Changes

Cohort / File(s) Summary
Resource Batch Processing Refactor
apps/api/src/modules/tool/resource.service.ts
Replaces per-resource sequential handling with batched processing via new batchProcessOutputResources. Adds helpers categorizeAndProcessResources and batchCreateAndCollectResults. Collects resource fields (including array-path expansions), categorizes URL vs non-URL tasks, batch-creates URL resources, maps results back into original data shape, and preserves direct-binary handling. Uses ExtendedUpsertDriveFileRequest in batch flows.
Tool-call result normalization
packages/ai-workspace-common/src/components/markdown/plugins/tool-call/render.tsx
Consolidates result extraction into a rawResult accumulator, reorders fallbacks (data-tool-result → API error → API output), centralizes JSON-parse/pretty-print normalization (handles double-escaped JSON), and returns empty string when no result present.
BillingConfig support in inventory
apps/api/src/modules/tool/inventory/inventory.service.ts
Extends creditBillingMap to accept numeric credits or full BillingConfig objects, adds isBillingConfig type guard, and introduces buildBillingConfig to produce validated BillingConfig instances for method billing. Exposes BillingConfig in imports.
Tool output parsing on events
apps/api/src/modules/skill/skill-invoker.service.ts
When handling on_tool_error and on_tool_end, attempts to JSON-parse event.data.output when it's a string and falls back to the original string if parsing fails; uses parsed object for persisted results and emitted events to ensure consistent typing.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files needing extra attention:
    • apps/api/src/modules/tool/resource.service.ts — batch construction, array-path expansion, mapping created DriveFile results to original payloads, and error propagation.
    • apps/api/src/modules/tool/inventory/inventory.service.ts — correctness of isBillingConfig guard and buildBillingConfig behavior for mixed inputs.
    • packages/.../render.tsx and apps/api/.../skill-invoker.service.ts — consistent JSON parsing/normalization and backward-compatible behavior for various tool-output shapes.

Possibly related PRs

Suggested reviewers

  • CH1111
  • nettee

Poem

🐇
I hopped through outputs one by one, then two,
Now I pack them tight and send them through.
URLs queued, results stitched in place,
The rabbit smiles — tidier trails, steady pace. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is mostly a template with placeholders and lacks a detailed summary of the actual changes, motivation, context, issue references, and impact area selections. Replace template placeholders with actual summary of batch processing implementation, explain the lock contention problem being solved, reference any related issue numbers, and select relevant impact areas.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: implement batch processing for output resources to reduce lock...' directly relates to the main change in resource.service.ts, which replaces sequential processing with batch-based approach.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tools/image-output

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/api/src/modules/tool/resource.service.ts (2)

231-238: Consider handling the case where a result is explicitly null.

The loop sets results back to their paths, but when result is null (indicating a failed upload), the original value gets replaced with null. This may silently lose data. Consider whether you want to preserve the original value when upload fails, or add logging for failed uploads.

     // Step 6: Set results back to their original paths in data
     for (let i = 0; i < resourceTasks.length; i++) {
       const task = resourceTasks[i];
       const result = taskResults.get(i);
-      if (result) {
+      if (result !== undefined) {
+        if (result === null) {
+          this.logger.warn(`Resource upload failed for path: ${task.path}, preserving original value`);
+          continue;
+        }
         _.set(data, task.path, result);
       }
     }

292-296: Non-URL resources are processed sequentially, reducing batch benefits.

The writeResource calls for non-URL resources (data URLs, base64, buffers) are awaited sequentially inside the loop. Consider collecting these as promises and processing them in parallel with Promise.all for consistency with the batch processing goal.

+    const nonUrlPromises: Array<{
+      taskIndex: number;
+      promise: Promise<DriveFile | null>;
+    }> = [];
+
     for (let i = 0; i < resourceTasks.length; i++) {
       const task = resourceTasks[i];
       const fileName = fileNameTitle
         ? i === 0
           ? fileNameTitle
           : `${fileNameTitle}-${i}`
         : undefined;

       // Check if value is a URL string
       if (typeof task.value === 'string' && this.isPublicUrl(task.value)) {
         // ... URL handling unchanged ...
       } else {
         // Handle non-URL resources individually (data URLs, base64, buffers)
-        const result = await this.writeResource(task.value, fileName, task.schema);
-        nonUrlResults.push({ taskIndex: i, result });
+        nonUrlPromises.push({
+          taskIndex: i,
+          promise: this.writeResource(task.value, fileName, task.schema),
+        });
       }
     }

+    // Await all non-URL resources in parallel
+    const resolvedNonUrl = await Promise.all(
+      nonUrlPromises.map(async ({ taskIndex, promise }) => ({
+        taskIndex,
+        result: await promise,
+      })),
+    );
+    nonUrlResults.push(...resolvedNonUrl);
+
     return { urlRequests, nonUrlResults };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0efaa0c and b503cdd.

📒 Files selected for processing (1)
  • apps/api/src/modules/tool/resource.service.ts (3 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 + b instead of a+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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)

**/*.{ts,tsx}: Avoid using any type whenever possible - use unknown type 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 the import type syntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types

Files:

  • apps/api/src/modules/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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-4 or p-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/tool/resource.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/tool/resource.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/tool/resource.service.ts
⏰ 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/tool/resource.service.ts (5)

15-15: LGTM!

The type import follows the coding guidelines by using import type syntax and is properly placed with related imports.


155-166: LGTM!

The integration of batch processing is clean and maintains the existing response structure while leveraging the new batch-based approach.


169-177: Well-structured batch processing implementation.

The step-by-step approach with clear comments makes the flow easy to follow. The separation of concerns between categorizing resources and batch creation is a good design choice that supports the PR's goal of reducing lock contention.


328-341: The order preservation assumption in the batch mapping is correct.

The batchCreateDriveFiles method in drive.service.ts (line 871) uses prisma.driveFile.createManyAndReturn() which returns results in the same order as the input data array. Since the input array is created via .map() at line 848, the order is preserved throughout the pipeline. The mapping at lines 334-336 in resource.service.ts correctly assumes that batchFiles[i] corresponds to urlRequests[i].


323-342: Error handling is already in place at the handler level.

The persistOutputResources method is called within a try-catch block in handler-post.ts (lines 64-111). If batchCreateDriveFiles fails, the exception is caught, logged, and the original response is returned to the user. Additionally, Prisma's createManyAndReturn is atomic—it either creates all records or throws entirely; partial batch failures are not possible with this API. The current all-or-nothing approach with error handling fallback is appropriate for this use case.

Copy link

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

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 207 to 210
} else {
const value = _.get(data, field.dataPath);
if (value !== undefined && value !== null) {
resourceTasks.push({ path: field.dataPath, value, schema: field.schema });

Choose a reason for hiding this comment

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

P1 Badge Preserve output resources in top-level array responses

For response schemas whose root type is an array (e.g., schema has items.properties.image.isResource), collectResourceFields yields paths like image with isArrayItem=false, so this branch reads values with _.get(data, field.dataPath) where data is the array and always gets undefined. resourceTasks stays empty and the method returns without uploading any files, meaning lists of resources are no longer persisted. The prior mapResourceFields path iterated array items before resolving resources, so this change regresses all array responses.

Useful? React with 👍 / 👎.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/ai-workspace-common/src/components/markdown/plugins/tool-call/render.tsx (1)

137-172: Result normalization looks correct; consider avoiding duplicate error display

The new rawResult flow and JSON re-stringification are correct and nicely handle both plain strings and double-escaped JSON without breaking existing behavior.

One small UX nit: when fetchedData?.data?.result?.error is present and there is no data-tool-result, resultContent becomes that error string, while errorMessage also uses the same value. This means the same error can appear twice, once under "Failure Reason" and again under "Output".

If you prefer to keep errors only in the dedicated failure section, you could treat the API error branch as “no result” for this memo:

-    } else if (fetchedData?.data?.result?.error) {
-      // Fall back to API data - error
-      return fetchedData.data.result.error;
+    } else if (fetchedData?.data?.result?.error) {
+      // Error is displayed in the dedicated failure section; do not duplicate in result
+      return '';

This keeps the new formatting behavior while avoiding duplicated error content in the UI.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b503cdd and 875ea22.

📒 Files selected for processing (1)
  • packages/ai-workspace-common/src/components/markdown/plugins/tool-call/render.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (19)
**/*.{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/markdown/plugins/tool-call/render.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 + b instead of a+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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)

**/*.{ts,tsx}: Avoid using any type whenever possible - use unknown type 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 the import type syntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types

Files:

  • packages/ai-workspace-common/src/components/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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-4 or p-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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.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/markdown/plugins/tool-call/render.tsx
⏰ 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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/api/src/modules/tool/inventory/inventory.service.ts (1)

324-346: Consider reusing the isBillingConfig type guard for consistency.

The method duplicates the type-checking logic from the isBillingConfig function (lines 329-335). Reusing the type guard would improve maintainability and ensure consistent validation logic.

Apply this diff to eliminate duplication:

   private buildBillingConfig(
     methodBilling: number | BillingConfig | undefined,
     defaultCreditsPerCall: number,
   ): BillingConfig {
     // If it's a full BillingConfig object, use it directly
-    if (
-      methodBilling &&
-      typeof methodBilling === 'object' &&
-      'enabled' in methodBilling &&
-      'type' in methodBilling
-    ) {
+    if (isBillingConfig(methodBilling)) {
       return methodBilling;
     }
 
     // Otherwise, create a PER_CALL config with the specified or default credits
     const credits = typeof methodBilling === 'number' ? methodBilling : defaultCreditsPerCall;
 
     return {
       enabled: true,
       type: BillingType.PER_CALL,
       creditsPerCall: credits,
     };
   }

Note: You'll need to change isBillingConfig from a local const to a private method or ensure it's accessible in this scope.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 875ea22 and 8e46127.

📒 Files selected for processing (1)
  • apps/api/src/modules/tool/inventory/inventory.service.ts (5 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 + b instead of a+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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)

**/*.{ts,tsx}: Avoid using any type whenever possible - use unknown type 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 the import type syntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types

Files:

  • apps/api/src/modules/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.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-4 or p-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/tool/inventory/inventory.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/tool/inventory/inventory.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/tool/inventory/inventory.service.ts
🧠 Learnings (1)
📚 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/tool/inventory/inventory.service.ts
🧬 Code graph analysis (1)
apps/api/src/modules/tool/inventory/inventory.service.ts (3)
packages/ai-workspace-common/src/requests/types.gen.ts (2)
  • BillingConfig (7977-8003)
  • BillingType (7975-7975)
packages/openapi-schema/src/types.gen.ts (2)
  • BillingConfig (7981-8007)
  • BillingType (7979-7979)
packages/request/src/requests/types.gen.ts (2)
  • BillingConfig (7977-8003)
  • BillingType (7975-7975)
⏰ 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 (4)
apps/api/src/modules/tool/inventory/inventory.service.ts (4)

9-14: LGTM! Import changes support the new BillingConfig functionality.

The addition of BillingConfig to the imports is correct and aligns with the schema types defined in @refly/openapi-schema.


171-172: LGTM! Type declaration enables backward compatibility.

The union type number | BillingConfig correctly supports both the legacy numeric format and the new structured billing configuration.


210-219: LGTM! Parsing logic correctly handles both formats.

The logic properly uses the isBillingConfig type guard to distinguish between full BillingConfig objects and simple numeric values, maintaining backward compatibility. Note that correct behavior depends on the isBillingConfig type guard working as expected (flagged separately).


191-203: Review comment is incorrect - no type mismatch exists.

The BillingType constant is properly defined as an enum with values PER_CALL = 'per_call' and PER_QUANTITY = 'per_quantity', which exactly match the string literals used in the schema. The type guard correctly validates against these enum values and will properly accept valid BillingConfig objects.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/api/src/modules/tool/resource.service.ts (1)

169-287: Batch collection and mapping back into data looks sound; minor duplication with mapResourceFields

The new batchProcessOutputResources correctly:

  • Applies omitFields before processing.
  • Uses collectResourceFields once, then builds resourceTasks for both object and array roots (including nested arrays via expandArrayPaths).
  • Maps taskResults back using stable task indices and lodash paths like [i].field.

This restores correct behavior for schemas whose root is an array (e.g., items with isResource fields) while enabling batched creation of URL-based resources.

There is some duplication with mapResourceFields (omitFields handling and resource field collection). If this pattern continues to evolve, consider extracting a shared helper (e.g., prepareResourceFields(schema, data)) to keep the behavior centralized.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e46127 and 76d8cfe.

📒 Files selected for processing (1)
  • apps/api/src/modules/tool/resource.service.ts (3 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 + b instead of a+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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)

**/*.{ts,tsx}: Avoid using any type whenever possible - use unknown type 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 the import type syntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types

Files:

  • apps/api/src/modules/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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/tool/resource.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-4 or p-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/tool/resource.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/tool/resource.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/tool/resource.service.ts
⏰ 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 (3)
apps/api/src/modules/tool/resource.service.ts (3)

15-15: Type-only import for batch file requests is appropriate

Using import type { ExtendedUpsertDriveFileRequest } keeps this as a pure compile-time dependency and avoids impacting the runtime bundle.


155-167: Batch wiring in persistOutputResources looks correct and restores array-root handling

Routing structured responses through batchProcessOutputResources keeps the direct-binary path intact and now explicitly handles both object and array root data. In particular, array-root responses will have their resource fields collected and persisted again instead of being skipped, addressing the earlier regression for top-level arrays.


351-391: Index-based mapping from batchCreateDriveFiles assumes stable ordering

batchCreateAndCollectResults relies on batchCreateDriveFiles returning batchFiles in the same order as the files array passed in, then re-associates results to tasks by index. That’s fine if the service guarantees order, but if it ever deduplicates, filters, or reorders, mappings could drift silently.

If the API already documents order preservation, this is good as-is. Otherwise, consider:

  • Having batchCreateDriveFiles return results tagged with a correlation key (e.g., externalUrl or an explicit taskIndex), or
  • Asserting batchFiles.length === urlRequests.length and logging when it does not, to make mismatches visible.

Comment on lines +312 to +341
for (let i = 0; i < resourceTasks.length; i++) {
const task = resourceTasks[i];
const fileName = fileNameTitle
? i === 0
? fileNameTitle
: `${fileNameTitle}-${i}`
: undefined;

// Check if value is a URL string
if (typeof task.value === 'string' && this.isPublicUrl(task.value)) {
const { filename } = this.inferFileInfoFromUrl(
task.value,
fileName || 'untitled',
'text/plain',
);
urlRequests.push({
taskIndex: i,
request: {
canvasId,
name: filename,
externalUrl: task.value,
source: 'agent',
resultId,
resultVersion,
},
});
} else {
// Handle non-URL resources individually (data URLs, base64, buffers)
const result = await this.writeResource(task.value, fileName, task.schema);
nonUrlResults.push({ taskIndex: i, result });
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Potential runtime error when fileNameTitle is missing (undefined passed into upload path)

When fileNameTitle is falsy, fileName becomes undefined, but the non-URL branch still passes it into writeResource. For plain-text outputs this eventually hits uploadTextResource, which calls fileName.endsWith(...) and will throw a TypeError if fileName is undefined.

This can occur whenever a tool emits a non-URL string resource and the caller did not supply file_name_title in the request.

Recommend always falling back to a concrete string (e.g. 'untitled') before calling writeResource and removing the || 'untitled' at the URL call site to keep it consistent:

-    for (let i = 0; i < resourceTasks.length; i++) {
-      const task = resourceTasks[i];
-      const fileName = fileNameTitle
-        ? i === 0
-          ? fileNameTitle
-          : `${fileNameTitle}-${i}`
-        : undefined;
+    for (let i = 0; i < resourceTasks.length; i++) {
+      const task = resourceTasks[i];
+      const baseFileName =
+        typeof fileNameTitle === 'string'
+          ? i === 0
+            ? fileNameTitle
+            : `${fileNameTitle}-${i}`
+          : 'untitled';
@@
-      if (typeof task.value === 'string' && this.isPublicUrl(task.value)) {
-        const { filename } = this.inferFileInfoFromUrl(
-          task.value,
-          fileName || 'untitled',
-          'text/plain',
-        );
+      if (typeof task.value === 'string' && this.isPublicUrl(task.value)) {
+        const { filename } = this.inferFileInfoFromUrl(
+          task.value,
+          baseFileName,
+          'text/plain',
+        );
@@
-      } else {
-        // Handle non-URL resources individually (data URLs, base64, buffers)
-        const result = await this.writeResource(task.value, fileName, task.schema);
+      } else {
+        // Handle non-URL resources individually (data URLs, base64, buffers)
+        const result = await this.writeResource(task.value, baseFileName, task.schema);

This ensures all upload paths receive a valid filename string and prevents crashes in the plain-text case.

🤖 Prompt for AI Agents
In apps/api/src/modules/tool/resource.service.ts around lines 312 to 341,
fileName can be undefined when fileNameTitle is falsy which later causes a
TypeError in upload paths that call fileName.endsWith; change the fileName
initialization so it always falls back to a concrete string (e.g. 'untitled')
instead of undefined, and remove the extra "|| 'untitled'" used only in the URL
branch so both URL and non-URL branches use the same guaranteed filename; ensure
writeResource and the URL request use that non-null filename.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/api/src/modules/skill/skill-invoker.service.ts (2)

720-725: Consider extracting the duplicate parsing logic into a helper function.

The JSON parsing logic for tool outputs appears identically in both on_tool_error and on_tool_end handlers. Extracting this into a reusable helper function would improve maintainability and ensure consistency.

Example helper function:

private parseToolOutput(rawOutput: unknown): unknown {
  return typeof rawOutput === 'string' 
    ? safeParseJSON(rawOutput) || rawOutput 
    : rawOutput;
}

Then use it in both handlers:

-              const rawErrorOutput = event.data?.output;
-              const errorToolOutput =
-                typeof rawErrorOutput === 'string'
-                  ? safeParseJSON(rawErrorOutput) || rawErrorOutput
-                  : rawErrorOutput;
+              const errorToolOutput = this.parseToolOutput(event.data?.output);
-              const rawToolOutput = event.data?.output;
-              const toolOutput =
-                typeof rawToolOutput === 'string'
-                  ? safeParseJSON(rawToolOutput) || rawToolOutput
-                  : rawToolOutput;
+              const toolOutput = this.parseToolOutput(event.data?.output);

Also applies to: 783-789


722-725: Consider improving type safety for parsed tool outputs.

The variables errorToolOutput and toolOutput are inferred as any because safeParseJSON likely returns any. For better type safety, consider typing the helper function (if extracted) with unknown and adding explicit type assertions or guards where the output is used.

Example with improved typing:

private parseToolOutput(rawOutput: unknown): unknown {
  return typeof rawOutput === 'string' 
    ? safeParseJSON(rawOutput) || rawOutput 
    : rawOutput;
}

Then use type guards or assertions where specific properties are accessed (e.g., toolOutput?.status, toolOutput?.error).

As per coding guidelines, prefer unknown over any for better type safety.

Also applies to: 786-789

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 76d8cfe and 7ce0127.

📒 Files selected for processing (1)
  • apps/api/src/modules/skill/skill-invoker.service.ts (3 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 + b instead of a+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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)

**/*.{ts,tsx}: Avoid using any type whenever possible - use unknown type 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 the import type syntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types

Files:

  • apps/api/src/modules/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.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-4 or p-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/skill/skill-invoker.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/skill/skill-invoker.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/skill/skill-invoker.service.ts
🧠 Learnings (1)
📚 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/skill/skill-invoker.service.ts
⏰ 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

@alchemistklk alchemistklk merged commit e8379de into main Dec 8, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants