fix: resolve all 610 ESLint errors across the codebase#380
fix: resolve all 610 ESLint errors across the codebase#380sweetmantech wants to merge 1 commit intotestfrom
Conversation
- Replace 233 `no-explicit-any` with proper types (unknown, specific interfaces) - Add meaningful JSDoc descriptions, @param, and @returns to 370+ functions - Remove 20 unused variables/imports - Fix param name mismatches, member ordering, import order, and tag-lines - All 1624 tests still pass Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughA comprehensive documentation update across 123 files adding and refining JSDoc comments for API routes, utility functions, and handlers. Includes targeted functional changes: removing Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ❌ 1❌ Failed checks (1 warning)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
lib/catalog/formatCatalogSongsAsCSV.ts (1)
10-13:⚠️ Potential issue | 🟠 MajorEscape embedded quotes to avoid invalid CSV rows.
Quoted CSV fields must escape inner
"characters. Current output breaks parsing when names/albums contain quotes.As per coding guidelines "lib/**/*.ts: For domain functions, ensure ... Proper error handling ... Use TypeScript for type safety".Proposed fix
export function formatCatalogSongsAsCSV(songs: CatalogSong[]): string { + const escapeCsv = (value: string): string => value.replace(/"/g, '""'); + const csvLines = songs.map(song => { - const artistNames = song.artists.map(artist => artist.name).join(", "); - return `${song.isrc},"${song.name}","${song.album}","${artistNames}"`; + const artistNames = song.artists.map(artist => artist.name).join(", "); + return `${song.isrc},"${escapeCsv(song.name)}","${escapeCsv(song.album)}","${escapeCsv(artistNames)}"`; }); return csvLines.join("\n"); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/catalog/formatCatalogSongsAsCSV.ts` around lines 10 - 13, The CSV builder in formatCatalogSongsAsCSV.ts doesn't escape embedded double quotes, breaking CSV parsing; implement an escape helper (e.g., escapeCsv(value: string)) that replaces all " with "" and use it when building csvLines for song.name, song.album and each artist.name (and any other quoted field), then wrap the escaped values in quotes when interpolating into the template (keep ISRC formatting consistent). Update the songs.map usage to apply escapeCsv to artist names joined, song.name and song.album so all quoted fields are safe.lib/ai/getAvailableModels.ts (1)
15-16: 🛠️ Refactor suggestion | 🟠 MajorAdd error logging in the catch block.
The empty catch block silently swallows all errors, making debugging difficult when the gateway API fails. Consider logging the error before returning the empty array to aid troubleshooting.
🔍 Proposed fix to add error logging
- } catch { + } catch (error) { + console.error("Failed to fetch available models from gateway:", error); return []; }Based on coding guidelines: "For domain functions, ensure: Proper error handling"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/ai/getAvailableModels.ts` around lines 15 - 16, The catch block in getAvailableModels (lib/ai/getAvailableModels.ts) currently swallows errors and returns [] — change it to capture the thrown error (e.g., catch (err)) and log the error with context before returning the empty array; use the project's logger (processLogger.error) if available, otherwise console.error, and include a message like "getAvailableModels: gateway API failed" plus the error details to aid debugging.
🧹 Nitpick comments (18)
lib/composio/getCallbackUrl.ts (1)
20-25: Use a named argument to avoidroot0JSDoc leakageThe generated
root0.*docs are hard to read. Prefer a named parameter (options) and destructure inside the function for clearer API docs.Proposed refactor
-/** - * Build callback URL for OAuth redirects. - * - * `@param` root0 - The callback options - * `@param` root0.destination - Where to redirect: "chat" or "connectors" - * `@param` root0.roomId - For chat destination, the room ID to return to - * `@returns` Full callback URL with success indicator - */ -export function getCallbackUrl({ destination, roomId }: CallbackOptions): string { +/** + * Build callback URL for OAuth redirects. + * + * `@param` options - The callback options + * `@param` options.destination - Where to redirect: "chat" or "connectors" + * `@param` options.roomId - For chat destination, the room ID to return to + * `@returns` Full callback URL with success indicator + */ +export function getCallbackUrl(options: CallbackOptions): string { + const { destination, roomId } = options; const baseUrl = getFrontendBaseUrl();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/composio/getCallbackUrl.ts` around lines 20 - 25, Replace the anonymous destructured parameter in getCallbackUrl with a named parameter to avoid `root0` in JSDoc: change the function signature to accept a single `options` object (e.g., getCallbackUrl(options: CallbackOptions)) and then destructure inside the function (const { destination, roomId } = options). Update the JSDoc param names to `options`, `options.destination`, and `options.roomId` so generated docs are clear, and keep the rest of the function logic unchanged.lib/catalog/getCatalogSongs.ts (1)
34-44: Add input guards for pagination arguments.Please validate
pageandpageSizebefore building query params to fail fast on invalid input.As per coding guidelines "lib/**/*.ts: For domain functions, ensure ... Proper error handling ... KISS: Prefer simple, readable implementations".Proposed guard
export async function getCatalogSongs( catalogId: string, pageSize: number = 100, page: number = 1, artistName?: string, ): Promise<CatalogSongsResponse> { + if (!catalogId.trim()) { + throw new Error("catalogId is required"); + } + if (!Number.isInteger(pageSize) || pageSize <= 0) { + throw new Error("pageSize must be a positive integer"); + } + if (!Number.isInteger(page) || page <= 0) { + throw new Error("page must be a positive integer"); + } + try {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/catalog/getCatalogSongs.ts` around lines 34 - 44, In getCatalogSongs, add input guards for the pagination args (page and pageSize) before constructing URLSearchParams: verify Number.isInteger(page) and Number.isInteger(pageSize) and that both are > 0 (optionally enforce a sensible max for pageSize), and throw a clear synchronous error (e.g., TypeError or RangeError) if validation fails; do this at the top of the getCatalogSongs function (before building params) so invalid inputs fail fast and avoid sending bad query params.lib/spotify/getSpotifyFollowers.ts (1)
44-66: Consider refining error handling and documenting the first-result behavior.Two optional improvements to enhance maintainability:
Error handling pattern (lines 63-64): Logging and then re-throwing can lead to duplicate log entries if the caller also logs. Consider either:
- Letting the error propagate without logging (caller handles logging), OR
- Wrapping in a domain-specific error type
First-result assumption (line 61): The function returns the follower count of the first search result without documenting this behavior. Consider adding a note to the JSDoc that clarifies this, e.g., "Returns the follower count of the first matching artist from Spotify search results."
♻️ Optional refactor: Remove redundant error logging
return data.artists.items[0].followers.total; } catch (error) { - console.error(`Error fetching Spotify followers for "${artistName}":`, error); throw error; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/spotify/getSpotifyFollowers.ts` around lines 44 - 66, Update getSpotifyFollowers to avoid duplicate logging and to document first-result behavior: remove the console.error from the catch block so errors simply propagate (or alternatively wrap and throw a domain-specific error type such as SpotifyFetchError from the catch), and add/extend the JSDoc for getSpotifyFollowers to state that it returns the follower count of the first matching artist returned by the Spotify search (i.e., first item in data.artists.items). Ensure references to getSpotifyFollowers and the catch block are updated accordingly.lib/artists/createArtistInDb.ts (1)
54-55: Preserve exception context in the catch pathAt Line 54, using a bare
catchdrops root-cause details, and this function already returnsnullfor non-exception branches. Please capture/log the error (or return a typed error result) so operational failures are debuggable.As per coding guidelines, for
lib/**/*.tsdomain functions, ensure “Proper error handling”.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/artists/createArtistInDb.ts` around lines 54 - 55, The catch block in createArtistInDb currently swallows exceptions (bare `catch`) and returns null; change it to `catch (err)` so the error is captured, then either log the error (using the module's logger or console.error) with context (e.g., "createArtistInDb failed") and return null, or return a typed error/result instead of null; update the `createArtistInDb` function to preserve and surface the caught exception rather than dropping it.lib/workspaces/createWorkspaceInDb.ts (1)
52-53: Avoid silent failure in catchAt Line 52, bare
catchremoves exception visibility while returningnull, which is also used for expected early exits. Capture/log the error (or return a discriminated result) so callers and logs can distinguish operational failures from validation-style nulls.As per coding guidelines, for
lib/**/*.tsdomain functions, ensure “Proper error handling”.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/workspaces/createWorkspaceInDb.ts` around lines 52 - 53, The bare catch in createWorkspaceInDb swallows exceptions and returns null (which overlaps with expected null exits); change the catch to catch (err) and do not silently return null — instead log the error with the project's logger (e.g., processLogger.error or the module logger) including a descriptive message like "Failed to create workspace in DB" and the error object, then rethrow the error (or return a discriminated result object such as { success: false, error: err } if the caller expects a non-throwing API) so operational failures are distinguishable from validation-style nulls.lib/supabase/storage/createSignedFileUrlByKey.ts (2)
23-25: Consider including the key in the error message for better debugging.While the error handling is solid, including the
keyparameter in the error message would make debugging easier, especially when processing multiple files.🔍 Suggested enhancement
if (error || !data?.signedUrl) { - throw new Error(`Failed to create signed URL: ${error?.message ?? "unknown error"}`); + throw new Error(`Failed to create signed URL for key "${key}": ${error?.message ?? "unknown error"}`); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/supabase/storage/createSignedFileUrlByKey.ts` around lines 23 - 25, The error throw in createSignedFileUrlByKey should include the input key to aid debugging; update the error construction in the block that checks (error || !data?.signedUrl) to append the value of the key parameter (e.g., `key`) to the message so the thrown Error contains both the original error message and the key being processed (keep existing fallback for unknown error and preserve current nullish checks).
14-14: Consider extracting the time calculation to a named constant.The inline calculation
60 * 60 * 24 * 7works but could be more readable as a named constant, especially if this duration is used elsewhere in the codebase. This would improve maintainability per the DRY principle in the coding guidelines.♻️ Suggested refactor
At the top of the file:
import supabase from "@/lib/supabase/serverClient"; import { SUPABASE_STORAGE_BUCKET } from "@/lib/const"; + +const SEVEN_DAYS_IN_SECONDS = 60 * 60 * 24 * 7;Then use it:
export async function createSignedFileUrlByKey({ key, - expiresInSeconds = 60 * 60 * 24 * 7, + expiresInSeconds = SEVEN_DAYS_IN_SECONDS, }: {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/supabase/storage/createSignedFileUrlByKey.ts` at line 14, Extract the inline default expiry calculation from the createSignedFileUrlByKey parameter (expiresInSeconds = 60 * 60 * 24 * 7) into a named top-level constant (e.g., DEFAULT_ONE_WEEK_SECONDS or DEFAULT_SIGNED_URL_TTL_SECONDS) and replace the inline expression with that constant; update any other places that use the same duration to reference the new constant to follow DRY and improve readability.lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts (1)
32-40: Consider usingresolveAccountId()for authentication (outside current PR scope).The tool directly uses
args.account_idandargs.artist_account_idfrom the input schema. For consistency with MCP authentication patterns, consider usingresolveAccountId()to validate and resolve account access.This is outside the scope of the current ESLint-fix PR but would align with the established MCP tool authentication pattern.
Based on learnings: "MCP tools should never manually extract
accountIdfromextra.authInfo; always useresolveAccountId()for validation and access control".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts` around lines 32 - 40, The code in the TranscribeAudio tool is directly using args.account_id and args.artist_account_id when calling processAudioTranscription; replace that manual extraction with the MCP auth helper by calling resolveAccountId() to validate/resolve the caller's account and any target artist account before calling processAudioTranscription. Concretely, in the TranscribeAudio handler (the async (args: TranscribeAudioArgs) => { ... }), call resolveAccountId() to obtain the resolved ownerAccountId and, if needed, resolve the artist account similarly, then pass those resolved IDs to processAudioTranscription instead of args.account_id and args.artist_account_id to follow MCP auth patterns.app/api/transcribe/route.ts (1)
14-30: Consider authentication and validation improvements (outside current PR scope).While the JSDoc changes look good, I noticed the existing implementation could benefit from future refactoring:
- The route accepts
account_iddirectly from the request body rather than deriving it from authentication viavalidateAuthContext()- Manual validation could be replaced with Zod schema validation
These are architectural concerns outside the scope of this ESLint-fix PR, but worth noting for a follow-up.
As per coding guidelines: "Never use
account_idin request bodies or tool schemas; always derive the account ID from authentication" and "All API endpoints should use a validate function for input parsing using Zod for schema validation".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/transcribe/route.ts` around lines 14 - 30, The endpoint POST currently trusts account_id from the request body and performs manual field checks; update it to derive account_id from the authentication context and switch input validation to a Zod schema. Specifically, call validateAuthContext() (or the project's auth helper) at the start of POST to obtain the account ID instead of reading body.account_id, define a Zod schema for { audio_url, artist_account_id, title?, include_timestamps? } and run it through the shared validate/parse helper used across the API, then remove the manual if-checks for audio_url/artist_account_id and return schema-driven errors. Ensure you still reject requests lacking audio_url or artist_account_id per the schema and use the authenticated account_id for downstream logic.lib/transcribe/processAudioTranscription.ts (1)
70-81: JSDoc is accurate; consider extending format coverage.The JSDoc clearly documents the helper's purpose. The implementation handles the most common audio formats well.
A few observations for potential future enhancement:
- Missing formats like
ogg,flac,aacwhich OpenAI Whisper supports- The substring matching is loose (e.g.,
contentType.includes("wav")would match bothaudio/wavandaudio/x-wav, which is likely intentional)Since
saveAudioToFilesuses thecontentTypeparameter for the actual MIME type (not the extension), this is primarily cosmetic for filenames and works correctly.🔧 Optional: Extended format coverage
function getExtensionFromContentType(contentType: string): string { if (contentType.includes("wav")) return "wav"; if (contentType.includes("m4a") || contentType.includes("mp4")) return "m4a"; if (contentType.includes("webm")) return "webm"; + if (contentType.includes("ogg")) return "ogg"; + if (contentType.includes("flac")) return "flac"; + if (contentType.includes("aac")) return "aac"; return "mp3"; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/transcribe/processAudioTranscription.ts` around lines 70 - 81, The helper getExtensionFromContentType currently maps a few audio MIME types but omits formats Whisper supports (ogg, flac, aac) and uses loose substring checks; update getExtensionFromContentType to explicitly handle "ogg", "flac", and "aac" (returning "ogg", "flac", and "aac" respectively) and tighten matching (e.g., match MIME subtype tokens rather than arbitrary substrings) so predictable file extensions are returned for MIME strings passed into saveAudioToFiles; reference the function name getExtensionFromContentType to locate and modify the logic.lib/supabase/storage/uploadFileByKey.ts (1)
4-12: Consider adding@returnsand@throwstags for comprehensive documentation.While the current JSDoc is clear and covers all parameters, adding
@returnsand@throwstags would provide a complete picture of the function's behavior for future maintainers.📝 Suggested enhancement
/** * Upload file to Supabase storage by key. * * `@param` key - The storage key (path) where the file will be stored * `@param` file - The file or blob data to upload * `@param` options - Optional upload configuration * `@param` options.contentType - MIME type of the file (defaults to application/octet-stream) * `@param` options.upsert - Whether to overwrite an existing file at the same key (defaults to false) + * `@returns` Resolves when the file upload completes successfully + * `@throws` {Error} When the upload operation fails */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/supabase/storage/uploadFileByKey.ts` around lines 4 - 12, The JSDoc for uploadFileByKey is missing `@returns` and `@throws` tags; update the comment above the uploadFileByKey function to include a clear `@returns` describing the Promise return type and what it resolves to (e.g., success result or response object) and an `@throws` that lists the kinds of errors that can be raised (validation errors, network/Supabase upload errors) — make sure the descriptions match the function's actual behavior and return shape so maintainers know what to expect.lib/content/getArtistRootPrefix.ts (1)
9-21: Consider adding input validation for improved robustness.While the function logic is clean and follows KISS principles, adding defensive input validation would improve reliability, especially since this is a utility function that may be called from various contexts:
- Validate that
pathsis a non-empty array- Validate that
artistSlugis a non-empty string- Consider sanitizing
artistSlugto prevent path traversal sequences (e.g.,../) or invalid charactersThese checks would prevent runtime errors and ensure predictable behavior with edge-case inputs.
🛡️ Example validation approach
export function getArtistRootPrefix(paths: string[], artistSlug: string): string { + if (!paths || paths.length === 0) { + throw new Error('paths array cannot be empty'); + } + if (!artistSlug || artistSlug.trim().length === 0) { + throw new Error('artistSlug cannot be empty'); + } + // Optional: sanitize artistSlug to prevent path traversal + const sanitizedSlug = artistSlug.replace(/\.\./g, '').replace(/^\/+|\/+$/g, ''); + - const preferredPrefix = `artists/${artistSlug}/`; + const preferredPrefix = `artists/${sanitizedSlug}/`; if (paths.some(path => path.startsWith(preferredPrefix))) { return preferredPrefix; } - const directPrefix = `${artistSlug}/`; + const directPrefix = `${sanitizedSlug}/`; if (paths.some(path => path.startsWith(directPrefix))) { return directPrefix; } return preferredPrefix; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/content/getArtistRootPrefix.ts` around lines 9 - 21, The function getArtistRootPrefix lacks input validation; add checks at the top of getArtistRootPrefix to ensure paths is a non-empty array of strings and artistSlug is a non-empty string, and either sanitize or reject artistSlug values that contain path traversal or invalid characters (e.g., '..' or '/'), throwing a clear TypeError for invalid inputs; after validation, preserve the existing logic that computes preferredPrefix and directPrefix and returns the matching prefix (preferredPrefix by default).lib/prompts/getSystemPrompt.ts (1)
20-133: Consider extracting section builders to reduce function length.The function body (~91 lines) exceeds the 50-line guideline. The three conditional sections (user context, artist instruction, knowledge base) follow a similar pattern and could be extracted into smaller helper functions.
This would improve:
- Compliance with the Single Responsibility Principle
- Code maintainability and testability
- Adherence to coding guidelines for domain functions
Since this PR focuses on ESLint fixes, this refactoring can be deferred to a future PR.
♻️ Example refactoring approach
Extract helper functions for each section:
function buildUserContextSection( accountWithDetails: AccountWithDetails, email?: string ): string { let section = `\n\n-----CURRENT USER CONTEXT-----\n...`; // ... existing logic from lines 68-107 return section; } function buildArtistInstructionSection(instruction: string): string { return `\n\n-----SELECTED ARTIST/WORKSPACE CONTEXT-----\n...`; } function buildKnowledgeBaseSection(text: string): string { return `\n\n-----ARTIST/WORKSPACE KNOWLEDGE BASE-----\n...`; } // Main function becomes much simpler: export function getSystemPrompt({...}: {...}): string { let systemPrompt = `${SYSTEM_PROMPT}\n\n**IMPORTANT CONTEXT VALUES...**`; if (accountWithDetails) { systemPrompt += buildUserContextSection(accountWithDetails, email); } if (artistInstruction) { systemPrompt += buildArtistInstructionSection(artistInstruction); } if (knowledgeBaseText) { systemPrompt += buildKnowledgeBaseSection(knowledgeBaseText); } return systemPrompt; }This would create a file structure following the "one exported function per file" principle by keeping the helpers private or in separate utility files.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/prompts/getSystemPrompt.ts` around lines 20 - 133, The getSystemPrompt function is over-long and should have its conditional sections extracted into helpers; refactor the user, artist, and knowledge-base blocks into small private functions (e.g., buildUserContextSection(accountWithDetails, email), buildArtistInstructionSection(artistInstruction), buildKnowledgeBaseSection(knowledgeBaseText)) and replace the inline string-building in getSystemPrompt with calls to these helpers so getSystemPrompt remains concise and each helper encapsulates the logic that currently lives in the blocks that reference accountWithDetails, artistInstruction, and knowledgeBaseText.lib/credits/getCreditUsage.ts (1)
28-31: Falsy check treats zero tokens as missing.The condition
!inputTokens || !outputTokensevaluates totruewhen tokens are0, logging "No tokens found in usage" even though zero is a valid token count. While the functional result (returning 0) is the same, the error message is misleading. Consider using nullish checks for semantic correctness.♻️ Proposed fix for precise null checking
- if (!inputTokens || !outputTokens) { + if (inputTokens == null || outputTokens == null) { console.error("No tokens found in usage"); return 0; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/credits/getCreditUsage.ts` around lines 28 - 31, The current falsy check in getCreditUsage incorrectly treats 0 as missing; change the condition that uses inputTokens and outputTokens (in getCreditUsage) to a nullish/undefined check (e.g., check inputTokens == null || outputTokens == null) so only null or undefined trigger the console.error("No tokens found in usage") and the early return 0; update the conditional to use those nullish checks and keep the same logging/return behavior when tokens are actually missing.lib/admins/content/extractVideoLinks.ts (1)
14-53: Consider extracting helper functions for readability.The function at 53 lines slightly exceeds the 50-line guideline. As per coding guidelines, lib functions should be kept under 50 lines. Similar to
extractGithubPrUrls, consider extracting the three extraction surfaces into focused helper functions:function extractUrlsFromText(text: string): string[] function extractUrlsFromAttachments(attachments?: SlackAttachment[]): string[] function extractUrlsFromBlocks(blocks?: SlackBlock[]): string[]This would improve maintainability and make each extraction logic easier to test independently.
Based on coding guidelines: "Keep functions under 50 lines" for
lib/**/*.tsfiles.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/admins/content/extractVideoLinks.ts` around lines 14 - 53, The extractVideoLinks function exceeds the 50-line guideline; split its three extraction responsibilities into small helpers to improve readability and testability: create extractUrlsFromText(text: string): string[] to run VIDEO_URL_PATTERN on text, extractUrlsFromAttachments(attachments?: SlackAttachment[]): string[] to iterate attachment.actions and collect action.url, and extractUrlsFromBlocks(blocks?: SlackBlock[]): string[] to walk block.elements and nested element.elements for element.url; then refactor extractVideoLinks to call these helpers, merge results, deduplicate with new Set, and return the final array.lib/admins/slack/extractGithubPrUrls.ts (1)
33-72: Consider splitting into smaller extraction functions.The function at 72 lines exceeds the 50-line guideline. As per coding guidelines, lib functions should be kept under 50 lines. Consider extracting the three extraction surfaces (text, attachments, blocks) into separate helper functions:
function extractFromText(text: string): string[] function extractFromAttachments(attachments?: SlackAttachment[]): string[] function extractFromBlocks(blocks?: SlackBlock[]): string[]This would improve testability and maintainability while adhering to the SRP principle.
Based on coding guidelines: "Keep functions under 50 lines" for
lib/**/*.tsfiles.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/admins/slack/extractGithubPrUrls.ts` around lines 33 - 72, The extractGithubPrUrls function is over the 50-line limit; split its three extraction responsibilities into separate helpers to follow SRP and improve testability: implement extractFromText(text: string): string[] to run PR_URL_PATTERN on the message text, extractFromAttachments(attachments?: SlackAttachment[]): string[] to scan attachment.actions and validate with PR_URL_EXACT, and extractFromBlocks(blocks?: SlackBlock[]): string[] to traverse block.elements and nested element.elements validating with PR_URL_EXACT; then refactor extractGithubPrUrls to call these three helpers, concatenate results, deduplicate (new Set) and return.app/api/accounts/[id]/route.ts (1)
26-28: Prefer a named route context overroot1in docs/signature.
root1is hard to read in API docs. Consider naming the second argcontextand documentingcontext.paramsinstead.♻️ Optional readability refactor
-/** - * `@param` request - The request object - * `@param` root1 - Destructured route context - * `@param` root1.params - Promise resolving to route params containing the account ID - */ -export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { - return getAccountHandler(request, params); +/** + * `@param` request - The request object + * `@param` context - Route context + * `@param` context.params - Promise resolving to route params containing the account ID + */ +export async function GET( + request: NextRequest, + context: { params: Promise<{ id: string }> }, +) { + return getAccountHandler(request, context.params); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/accounts/`[id]/route.ts around lines 26 - 28, The JSDoc and function signature use the unclear name root1 for the route context; rename it to context everywhere (both in the GET handler signature and the JSDoc) and update the param docs to reference context.params instead of root1.params so docs/readability improve — change occurrences in the GET function declaration and the related JSDoc `@param` entries to use context and context.params.lib/content/getArtistFileTree.ts (1)
7-10: JSDoc return description doesn't fully capture the fallback behavior.The
@returnsstates "or null if not found," but line 37 returnsmainTreeunconditionally after exhausting the org repos search. This means if the artist isn't found in any repo, the function returns the main repo's file tree (if it exists) rather thannull. The only way to getnullis ifgetRepoFileTree(githubRepo)returnsnull.Consider clarifying the return contract:
📝 Suggested JSDoc refinement
* `@param` githubRepo - The GitHub repository URL to search first. * `@param` artistSlug - The artist's directory slug to locate within the repo. -* `@returns` The file tree entries for the repo that contains the artist, or null if not found. +* `@returns` The file tree for the repo containing the artist, or the main repo's tree as a fallback, or null if the main repo tree couldn't be fetched.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/content/getArtistFileTree.ts` around lines 7 - 10, Update the JSDoc for getArtistFileTree to accurately describe its fallback behavior: explain that it returns the file tree for the repo that contains artistSlug if found, otherwise it returns the main repo's file tree obtained from getRepoFileTree(githubRepo) (which itself may be null) — i.e., the function only returns null when getRepoFileTree(githubRepo) returns null; mention the mainTree fallback and reference artistSlug, githubRepo, getRepoFileTree, and mainTree in the description.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/api/connectors/route.ts`:
- Line 30: Remove all client-supplied account_id handling in the connectors
endpoints: stop reading account_id from query or request bodies and derive the
account ID exclusively from validateAuthContext() for the GET /api/connectors
handler, the POST /api/connectors/authorize handler, and the DELETE
/api/connectors handler. Update the handlers (functions/methods that parse
request.query.account_id, request.body.account_id or similar) to use the
accountId returned by validateAuthContext(), remove any conditional access
checks based on an optional account_id input, and adjust related TypeScript
types and JSDoc comments (the param lines in the file) to reflect that
account_id is not accepted from the client. Ensure all authorization/enforcement
still runs but now uses the accountId from validateAuthContext() only.
In `@lib/admins/slack/getCutoffTs.ts`:
- Around line 8-10: The JSDoc `@returns` for getCutoffTs is misleading — the
function returns "current time minus the period length" (a rolling cutoff), not
the calendar start of the period; update the comment in getCutoffTs to say:
"Unix timestamp in seconds representing current time minus the period length
(rolling cutoff), or null for 'all'." Ensure the updated wording appears where
the `@returns` is declared to match the getCutoffTs implementation.
In `@lib/coding-agent/mergeGithubBranch.ts`:
- Line 19: mergeGithubBranch and mergeGithubPR currently call
JSON.parse(errorBody) on error paths which can throw and break the documented
return contract; update both functions so the JSON.parse(errorBody) is wrapped
in a try-catch and never allowed to throw — on parse success extract a
meaningful message, on failure fall back to using the raw errorBody or a generic
message, then return { ok: false, message } so the function always returns the
documented union; locate the JSON.parse usage in mergeGithubBranch and
mergeGithubPR and implement this guarded parsing behavior.
In `@lib/content/validateGetContentValidateQuery.ts`:
- Around line 16-19: Replace the manual parsing of artist_account_id in the
validateGetContentValidateQuery module with a Zod-backed validator: define a Zod
schema (e.g., GetContentQuerySchema) that validates the incoming query shape
(including artist_account_id as the required string/UUID pattern you expect),
use schema.parse or schema.safeParse inside validateGetContentValidateQuery to
validate and extract values, export the inferred type (e.g., type
GetContentQuery = z.infer<typeof GetContentQuerySchema>), and update the
function to return the typed validated data (account ID, artist_account_id,
resolved artist slug) or a NextResponse error on failure; reference the existing
validateGetContentValidateQuery function and export names when making these
changes.
---
Outside diff comments:
In `@lib/ai/getAvailableModels.ts`:
- Around line 15-16: The catch block in getAvailableModels
(lib/ai/getAvailableModels.ts) currently swallows errors and returns [] — change
it to capture the thrown error (e.g., catch (err)) and log the error with
context before returning the empty array; use the project's logger
(processLogger.error) if available, otherwise console.error, and include a
message like "getAvailableModels: gateway API failed" plus the error details to
aid debugging.
In `@lib/catalog/formatCatalogSongsAsCSV.ts`:
- Around line 10-13: The CSV builder in formatCatalogSongsAsCSV.ts doesn't
escape embedded double quotes, breaking CSV parsing; implement an escape helper
(e.g., escapeCsv(value: string)) that replaces all " with "" and use it when
building csvLines for song.name, song.album and each artist.name (and any other
quoted field), then wrap the escaped values in quotes when interpolating into
the template (keep ISRC formatting consistent). Update the songs.map usage to
apply escapeCsv to artist names joined, song.name and song.album so all quoted
fields are safe.
---
Nitpick comments:
In `@app/api/accounts/`[id]/route.ts:
- Around line 26-28: The JSDoc and function signature use the unclear name root1
for the route context; rename it to context everywhere (both in the GET handler
signature and the JSDoc) and update the param docs to reference context.params
instead of root1.params so docs/readability improve — change occurrences in the
GET function declaration and the related JSDoc `@param` entries to use context and
context.params.
In `@app/api/transcribe/route.ts`:
- Around line 14-30: The endpoint POST currently trusts account_id from the
request body and performs manual field checks; update it to derive account_id
from the authentication context and switch input validation to a Zod schema.
Specifically, call validateAuthContext() (or the project's auth helper) at the
start of POST to obtain the account ID instead of reading body.account_id,
define a Zod schema for { audio_url, artist_account_id, title?,
include_timestamps? } and run it through the shared validate/parse helper used
across the API, then remove the manual if-checks for audio_url/artist_account_id
and return schema-driven errors. Ensure you still reject requests lacking
audio_url or artist_account_id per the schema and use the authenticated
account_id for downstream logic.
In `@lib/admins/content/extractVideoLinks.ts`:
- Around line 14-53: The extractVideoLinks function exceeds the 50-line
guideline; split its three extraction responsibilities into small helpers to
improve readability and testability: create extractUrlsFromText(text: string):
string[] to run VIDEO_URL_PATTERN on text,
extractUrlsFromAttachments(attachments?: SlackAttachment[]): string[] to iterate
attachment.actions and collect action.url, and extractUrlsFromBlocks(blocks?:
SlackBlock[]): string[] to walk block.elements and nested element.elements for
element.url; then refactor extractVideoLinks to call these helpers, merge
results, deduplicate with new Set, and return the final array.
In `@lib/admins/slack/extractGithubPrUrls.ts`:
- Around line 33-72: The extractGithubPrUrls function is over the 50-line limit;
split its three extraction responsibilities into separate helpers to follow SRP
and improve testability: implement extractFromText(text: string): string[] to
run PR_URL_PATTERN on the message text, extractFromAttachments(attachments?:
SlackAttachment[]): string[] to scan attachment.actions and validate with
PR_URL_EXACT, and extractFromBlocks(blocks?: SlackBlock[]): string[] to traverse
block.elements and nested element.elements validating with PR_URL_EXACT; then
refactor extractGithubPrUrls to call these three helpers, concatenate results,
deduplicate (new Set) and return.
In `@lib/artists/createArtistInDb.ts`:
- Around line 54-55: The catch block in createArtistInDb currently swallows
exceptions (bare `catch`) and returns null; change it to `catch (err)` so the
error is captured, then either log the error (using the module's logger or
console.error) with context (e.g., "createArtistInDb failed") and return null,
or return a typed error/result instead of null; update the `createArtistInDb`
function to preserve and surface the caught exception rather than dropping it.
In `@lib/catalog/getCatalogSongs.ts`:
- Around line 34-44: In getCatalogSongs, add input guards for the pagination
args (page and pageSize) before constructing URLSearchParams: verify
Number.isInteger(page) and Number.isInteger(pageSize) and that both are > 0
(optionally enforce a sensible max for pageSize), and throw a clear synchronous
error (e.g., TypeError or RangeError) if validation fails; do this at the top of
the getCatalogSongs function (before building params) so invalid inputs fail
fast and avoid sending bad query params.
In `@lib/composio/getCallbackUrl.ts`:
- Around line 20-25: Replace the anonymous destructured parameter in
getCallbackUrl with a named parameter to avoid `root0` in JSDoc: change the
function signature to accept a single `options` object (e.g.,
getCallbackUrl(options: CallbackOptions)) and then destructure inside the
function (const { destination, roomId } = options). Update the JSDoc param names
to `options`, `options.destination`, and `options.roomId` so generated docs are
clear, and keep the rest of the function logic unchanged.
In `@lib/content/getArtistFileTree.ts`:
- Around line 7-10: Update the JSDoc for getArtistFileTree to accurately
describe its fallback behavior: explain that it returns the file tree for the
repo that contains artistSlug if found, otherwise it returns the main repo's
file tree obtained from getRepoFileTree(githubRepo) (which itself may be null) —
i.e., the function only returns null when getRepoFileTree(githubRepo) returns
null; mention the mainTree fallback and reference artistSlug, githubRepo,
getRepoFileTree, and mainTree in the description.
In `@lib/content/getArtistRootPrefix.ts`:
- Around line 9-21: The function getArtistRootPrefix lacks input validation; add
checks at the top of getArtistRootPrefix to ensure paths is a non-empty array of
strings and artistSlug is a non-empty string, and either sanitize or reject
artistSlug values that contain path traversal or invalid characters (e.g., '..'
or '/'), throwing a clear TypeError for invalid inputs; after validation,
preserve the existing logic that computes preferredPrefix and directPrefix and
returns the matching prefix (preferredPrefix by default).
In `@lib/credits/getCreditUsage.ts`:
- Around line 28-31: The current falsy check in getCreditUsage incorrectly
treats 0 as missing; change the condition that uses inputTokens and outputTokens
(in getCreditUsage) to a nullish/undefined check (e.g., check inputTokens ==
null || outputTokens == null) so only null or undefined trigger the
console.error("No tokens found in usage") and the early return 0; update the
conditional to use those nullish checks and keep the same logging/return
behavior when tokens are actually missing.
In `@lib/mcp/tools/transcribe/registerTranscribeAudioTool.ts`:
- Around line 32-40: The code in the TranscribeAudio tool is directly using
args.account_id and args.artist_account_id when calling
processAudioTranscription; replace that manual extraction with the MCP auth
helper by calling resolveAccountId() to validate/resolve the caller's account
and any target artist account before calling processAudioTranscription.
Concretely, in the TranscribeAudio handler (the async (args:
TranscribeAudioArgs) => { ... }), call resolveAccountId() to obtain the resolved
ownerAccountId and, if needed, resolve the artist account similarly, then pass
those resolved IDs to processAudioTranscription instead of args.account_id and
args.artist_account_id to follow MCP auth patterns.
In `@lib/prompts/getSystemPrompt.ts`:
- Around line 20-133: The getSystemPrompt function is over-long and should have
its conditional sections extracted into helpers; refactor the user, artist, and
knowledge-base blocks into small private functions (e.g.,
buildUserContextSection(accountWithDetails, email),
buildArtistInstructionSection(artistInstruction),
buildKnowledgeBaseSection(knowledgeBaseText)) and replace the inline
string-building in getSystemPrompt with calls to these helpers so
getSystemPrompt remains concise and each helper encapsulates the logic that
currently lives in the blocks that reference accountWithDetails,
artistInstruction, and knowledgeBaseText.
In `@lib/spotify/getSpotifyFollowers.ts`:
- Around line 44-66: Update getSpotifyFollowers to avoid duplicate logging and
to document first-result behavior: remove the console.error from the catch block
so errors simply propagate (or alternatively wrap and throw a domain-specific
error type such as SpotifyFetchError from the catch), and add/extend the JSDoc
for getSpotifyFollowers to state that it returns the follower count of the first
matching artist returned by the Spotify search (i.e., first item in
data.artists.items). Ensure references to getSpotifyFollowers and the catch
block are updated accordingly.
In `@lib/supabase/storage/createSignedFileUrlByKey.ts`:
- Around line 23-25: The error throw in createSignedFileUrlByKey should include
the input key to aid debugging; update the error construction in the block that
checks (error || !data?.signedUrl) to append the value of the key parameter
(e.g., `key`) to the message so the thrown Error contains both the original
error message and the key being processed (keep existing fallback for unknown
error and preserve current nullish checks).
- Line 14: Extract the inline default expiry calculation from the
createSignedFileUrlByKey parameter (expiresInSeconds = 60 * 60 * 24 * 7) into a
named top-level constant (e.g., DEFAULT_ONE_WEEK_SECONDS or
DEFAULT_SIGNED_URL_TTL_SECONDS) and replace the inline expression with that
constant; update any other places that use the same duration to reference the
new constant to follow DRY and improve readability.
In `@lib/supabase/storage/uploadFileByKey.ts`:
- Around line 4-12: The JSDoc for uploadFileByKey is missing `@returns` and
`@throws` tags; update the comment above the uploadFileByKey function to include a
clear `@returns` describing the Promise return type and what it resolves to (e.g.,
success result or response object) and an `@throws` that lists the kinds of errors
that can be raised (validation errors, network/Supabase upload errors) — make
sure the descriptions match the function's actual behavior and return shape so
maintainers know what to expect.
In `@lib/transcribe/processAudioTranscription.ts`:
- Around line 70-81: The helper getExtensionFromContentType currently maps a few
audio MIME types but omits formats Whisper supports (ogg, flac, aac) and uses
loose substring checks; update getExtensionFromContentType to explicitly handle
"ogg", "flac", and "aac" (returning "ogg", "flac", and "aac" respectively) and
tighten matching (e.g., match MIME subtype tokens rather than arbitrary
substrings) so predictable file extensions are returned for MIME strings passed
into saveAudioToFiles; reference the function name getExtensionFromContentType
to locate and modify the logic.
In `@lib/workspaces/createWorkspaceInDb.ts`:
- Around line 52-53: The bare catch in createWorkspaceInDb swallows exceptions
and returns null (which overlaps with expected null exits); change the catch to
catch (err) and do not silently return null — instead log the error with the
project's logger (e.g., processLogger.error or the module logger) including a
descriptive message like "Failed to create workspace in DB" and the error
object, then rethrow the error (or return a discriminated result object such as
{ success: false, error: err } if the caller expects a non-throwing API) so
operational failures are distinguishable from validation-style nulls.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bad7ff9c-69b3-4310-ad24-eb4dd193bdd4
⛔ Files ignored due to path filters (74)
lib/admins/content/__tests__/getContentSlackTagsHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/admins/emails/__tests__/validateGetAdminEmailsQuery.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/admins/pr/__tests__/getPrMergedStatusHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/admins/privy/__tests__/getPrivyLoginsHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/admins/privy/__tests__/validateGetPrivyLoginsQuery.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/admins/slack/__tests__/createSlackTagsHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/admins/slack/__tests__/getSlackTagsHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/admins/slack/__tests__/validateGetSlackTagsQuery.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/agents/generalAgent/__tests__/getGeneralAgent.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/ai/__tests__/getAvailableModels.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/ai/__tests__/getModel.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/artist/__tests__/updateArtistSocials.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/artists/__tests__/createArtistPostHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/artists/__tests__/validateCreateArtistBody.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/auth/__tests__/validateAuthContext.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/handleChatCompletion.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/handleChatGenerate.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/handleChatStream.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/integration/chatEndToEnd.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/saveChatCompletion.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/setupChatRequest.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/validateChatRequest.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/toolChains/__tests__/getExecutedToolTimeline.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/toolChains/__tests__/getPrepareStepResult.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/toolChains/__tests__/toolChains.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chats/__tests__/createChatHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chats/__tests__/generateChatTitle.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chats/__tests__/getChatsHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chats/__tests__/validateCreateChatBody.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chats/__tests__/validateGetChatsRequest.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/handleCodingAgentCallback.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/handleGitHubWebhook.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/handlers.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/mergeGithubBranch.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/mergeGithubPR.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/onMergeAction.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/onMergeTestToMainAction.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/onSubscribedMessage.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/coding-agent/__tests__/resolvePRState.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/content/__tests__/validateCreateContentBody.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/credits/__tests__/getCreditUsage.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/emails/inbound/__tests__/validateNewEmailMemory.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/evals/callChatFunctions.tsis excluded by!**/evals/**and included bylib/**lib/evals/callChatFunctionsWithResult.tsis excluded by!**/evals/**and included bylib/**lib/evals/createToolsCalledScorer.tsis excluded by!**/evals/**and included bylib/**lib/evals/extractTextFromResult.tsis excluded by!**/evals/**and included bylib/**lib/evals/extractTextResultFromSteps.tsis excluded by!**/evals/**and included bylib/**lib/evals/getCatalogSongsCountExpected.tsis excluded by!**/evals/**and included bylib/**lib/evals/getSpotifyFollowersExpected.tsis excluded by!**/evals/**and included bylib/**lib/evals/scorers/CatalogAvailability.tsis excluded by!**/evals/**and included bylib/**lib/evals/scorers/QuestionAnswered.tsis excluded by!**/evals/**and included bylib/**lib/evals/scorers/ToolsCalled.tsis excluded by!**/evals/**and included bylib/**lib/flamingo/__tests__/getFlamingoPresetsHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/github/__tests__/createOrUpdateFileContent.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/github/__tests__/expandSubmoduleEntries.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/__tests__/getMcpTools.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/tools/artists/__tests__/registerCreateNewArtistTool.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/tools/pulse/__tests__/registerGetPulsesTool.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/tools/pulse/__tests__/registerUpdatePulseTool.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/tools/sandbox/__tests__/registerPromptSandboxTool.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/tools/tasks/__tests__/registerGetTaskRunStatusTool.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/messages/__tests__/convertToUiMessages.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/messages/__tests__/getTextContent.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/notifications/__tests__/createNotificationHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/notifications/__tests__/validateCreateNotificationBody.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/prompts/__tests__/getSystemPrompt.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/sandbox/__tests__/deleteSandboxHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/sandbox/__tests__/postSandboxesFilesHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/sandbox/__tests__/validateDeleteSandboxBody.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/account_sandboxes/__tests__/selectAccountSandboxes.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/tasks/__tests__/enrichTaskWithTriggerInfo.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/tasks/__tests__/getTaskRunHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/tasks/__tests__/validateGetTaskRunQuery.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/tasks/__tests__/validateGetTasksQuery.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**
📒 Files selected for processing (108)
app/api/accounts/[id]/route.tsapp/api/admins/coding/pr/route.tsapp/api/admins/coding/slack/route.tsapp/api/admins/content/slack/route.tsapp/api/admins/privy/route.tsapp/api/coding-agent/callback/route.tsapp/api/coding-agent/github/route.tsapp/api/connectors/route.tsapp/api/songs/analyze/presets/route.tsapp/api/transcribe/route.tslib/accounts/validateOverrideAccountId.tslib/admins/content/extractVideoLinks.tslib/admins/content/fetchThreadVideoLinks.tslib/admins/pr/getPrStatusHandler.tslib/admins/privy/countNewAccounts.tslib/admins/privy/fetchPrivyLogins.tslib/admins/privy/getCutoffMs.tslib/admins/privy/getLatestVerifiedAt.tslib/admins/privy/toMs.tslib/admins/slack/createSlackTagsHandler.tslib/admins/slack/extractGithubPrUrls.tslib/admins/slack/fetchThreadPullRequests.tslib/admins/slack/getCutoffTs.tslib/ai/getAvailableModels.tslib/ai/getModel.tslib/ai/isEmbedModel.tslib/artists/createArtistInDb.tslib/catalog/formatCatalogSongsAsCSV.tslib/catalog/getCatalogDataAsCSV.tslib/catalog/getCatalogSongs.tslib/catalog/getCatalogs.tslib/chat/toolChains/create_release_report/getReleaseReportReferenceMessage.tslib/chat/toolChains/getPrepareStepResult.tslib/chats/compactChatsHandler.tslib/chats/processCompactChatRequest.tslib/chats/validateUpdateChatBody.tslib/coding-agent/buildMergeTestToMainCard.tslib/coding-agent/buildPRCard.tslib/coding-agent/buildTaskCard.tslib/coding-agent/encodeGitHubThreadId.tslib/coding-agent/extractPRComment.tslib/coding-agent/handleGitHubWebhook.tslib/coding-agent/handleMergeSuccess.tslib/coding-agent/handlePRCreated.tslib/coding-agent/handlers/handleFeedback.tslib/coding-agent/handlers/onMergeAction.tslib/coding-agent/handlers/onMergeTestToMainAction.tslib/coding-agent/handlers/onNewMention.tslib/coding-agent/handlers/onSubscribedMessage.tslib/coding-agent/mergeGithubBranch.tslib/coding-agent/mergeGithubPR.tslib/coding-agent/parseMergeActionId.tslib/coding-agent/parseMergeTestToMainActionId.tslib/coding-agent/prState/buildPRStateKey.tslib/coding-agent/prState/deleteCodingAgentPRState.tslib/coding-agent/prState/getCodingAgentPRState.tslib/coding-agent/prState/setCodingAgentPRState.tslib/coding-agent/resolvePRState.tslib/coding-agent/verifyGitHubWebhook.tslib/coding-agent/whatsApp/isWhatsAppConfigured.tslib/composio/client.tslib/composio/connectors/isAllowedArtistConnector.tslib/composio/getCallbackUrl.tslib/composio/getFrontendBaseUrl.tslib/composio/toolRouter/createToolRouterSession.tslib/content/contentTemplates.tslib/content/createContentHandler.tslib/content/getArtistContentReadiness.tslib/content/getArtistFileTree.tslib/content/getArtistRootPrefix.tslib/content/getContentEstimateHandler.tslib/content/getContentTemplatesHandler.tslib/content/getContentValidateHandler.tslib/content/isCompletedRun.tslib/content/persistCreateContentRunVideo.tslib/content/validateCreateContentBody.tslib/content/validateGetContentEstimateQuery.tslib/content/validateGetContentValidateQuery.tslib/credits/getCreditUsage.tslib/credits/handleChatCredits.tslib/emails/processAndSendEmail.tslib/flamingo/getFlamingoPresetsHandler.tslib/flamingo/postFlamingoGenerateHandler.tslib/github/expandSubmoduleEntries.tslib/github/getRepoGitModules.tslib/github/resolveSubmodulePath.tslib/mcp/resolveAccountId.tslib/mcp/tools/flamingo/registerAnalyzeMusicTool.tslib/mcp/tools/transcribe/registerTranscribeAudioTool.tslib/prompts/getSystemPrompt.tslib/slack/getBotChannels.tslib/slack/getBotUserId.tslib/slack/getSlackUserInfo.tslib/spotify/getSpotifyFollowers.tslib/supabase/account_artist_ids/getAccountArtistIds.tslib/supabase/account_workspace_ids/getAccountWorkspaceIds.tslib/supabase/files/createFileRecord.tslib/supabase/files/selectFileByStorageKey.tslib/supabase/song_artists/insertSongArtists.tslib/supabase/storage/createSignedFileUrlByKey.tslib/supabase/storage/uploadFileByKey.tslib/transcribe/processAudioTranscription.tslib/transcribe/saveAudioToFiles.tslib/transcribe/saveTranscriptToFiles.tslib/transcribe/types.tslib/trigger/fetchTriggerRuns.tslib/trigger/triggerCreateContent.tslib/workspaces/createWorkspaceInDb.ts
| * Authentication: x-api-key OR Authorization Bearer token required. | ||
| * | ||
| * @param request | ||
| * @param request - The incoming request with optional account_id query param |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locate connector handlers:"
fd -i 'getConnectorsHandler.ts|authorizeConnectorHandler.ts|disconnectConnectorHandler.ts' lib
echo
echo "Check for account_id parsing/usages and auth context validation in those handlers:"
rg -n -C3 --type=ts '\baccount_id\b|searchParams\.get\("account_id"\)|validateAuthContext\(' lib/composio/connectorsRepository: recoupable/api
Length of output: 47897
Remove account_id parameter support across all connector endpoints (GET, POST, DELETE).
The current API design accepts optional account_id in query params (GET) and request bodies (POST, DELETE), which violates the authentication model. Per coding guidelines, account identity must derive solely from authentication context—never from client input. This applies to:
- GET /api/connectors:
account_idquery param (documented in line 30) - POST /api/connectors/authorize:
account_idbody field (documented in line 49) - DELETE /api/connectors:
account_idbody field (documented in line 67–68)
The handlers currently accept account_id as optional with access checks, but the entire pattern conflicts with the guideline. Refactor to derive the account ID from validateAuthContext() alone. If multi-tenant access is needed, implement it through a separate, explicit authorization mechanism—not through optional client parameters.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/api/connectors/route.ts` at line 30, Remove all client-supplied
account_id handling in the connectors endpoints: stop reading account_id from
query or request bodies and derive the account ID exclusively from
validateAuthContext() for the GET /api/connectors handler, the POST
/api/connectors/authorize handler, and the DELETE /api/connectors handler.
Update the handlers (functions/methods that parse request.query.account_id,
request.body.account_id or similar) to use the accountId returned by
validateAuthContext(), remove any conditional access checks based on an optional
account_id input, and adjust related TypeScript types and JSDoc comments (the
param lines in the file) to reflect that account_id is not accepted from the
client. Ensure all authorization/enforcement still runs but now uses the
accountId from validateAuthContext() only.
| * @param period - The time window ("daily", "weekly", "monthly", or "all") to compute a cutoff for. | ||
| * @returns Unix timestamp in seconds representing the start of the period, or null for "all". | ||
| */ |
There was a problem hiding this comment.
@returns wording does not match current cutoff semantics.
At Line 14, the value is “current time minus period length,” not strictly the calendar “start of the period.” Please adjust wording (or change implementation) to avoid ambiguity.
📝 Suggested doc fix
- * `@returns` Unix timestamp in seconds representing the start of the period, or null for "all".
+ * `@returns` Unix timestamp in seconds computed as now minus the selected period, or null for "all".📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| * @param period - The time window ("daily", "weekly", "monthly", or "all") to compute a cutoff for. | |
| * @returns Unix timestamp in seconds representing the start of the period, or null for "all". | |
| */ | |
| * `@param` period - The time window ("daily", "weekly", "monthly", or "all") to compute a cutoff for. | |
| * `@returns` Unix timestamp in seconds computed as now minus the selected period, or null for "all". | |
| */ |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/admins/slack/getCutoffTs.ts` around lines 8 - 10, The JSDoc `@returns` for
getCutoffTs is misleading — the function returns "current time minus the period
length" (a rolling cutoff), not the calendar start of the period; update the
comment in getCutoffTs to say: "Unix timestamp in seconds representing current
time minus the period length (rolling cutoff), or null for 'all'." Ensure the
updated wording appears where the `@returns` is declared to match the getCutoffTs
implementation.
| * @param head - Branch to merge from (e.g. "test") | ||
| * @param base - Branch to merge into (e.g. "main") | ||
| * @param token - GitHub API token | ||
| * @returns An object with ok: true on success, or ok: false with a message on failure |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify unguarded JSON.parse usage in coding-agent merge helpers.
rg -n -C2 'JSON\.parse\(errorBody\)' --type=tsRepository: recoupable/api
Length of output: 837
🏁 Script executed:
#!/bin/bash
# Check function signatures and return types for both merge functions
echo "=== mergeGithubBranch.ts ==="
sed -n '1,30p' lib/coding-agent/mergeGithubBranch.ts | head -25
echo -e "\n=== mergeGithubPR.ts ==="
sed -n '1,30p' lib/coding-agent/mergeGithubPR.ts | head -25Repository: recoupable/api
Length of output: 1467
Unguarded JSON.parse in error paths violates return type contract.
Both mergeGithubBranch and mergeGithubPR document a deterministic return: { ok: true } | { ok: false, message: string }. However, JSON.parse(errorBody) at lines 51 (mergeGithubBranch.ts) and 47 (mergeGithubPR.ts) can throw if GitHub or an intermediary returns non-JSON, causing rejection instead of the promised failure object. This breaks the contract and violates the error handling requirement.
Wrap parsing in try-catch with a fallback message:
Proposed fix
const errorBody = await response.text();
console.error(
`[coding-agent] ... ${response.status} ${errorBody}`,
);
- const error = JSON.parse(errorBody);
- return { ok: false, message: error.message };
+ let message = `GitHub merge failed with status ${response.status}`;
+ try {
+ const error = JSON.parse(errorBody) as { message?: string };
+ if (error.message) message = error.message;
+ } catch {
+ if (errorBody.trim()) message = errorBody.trim();
+ }
+ return { ok: false, message };Apply the same fix to both files.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/coding-agent/mergeGithubBranch.ts` at line 19, mergeGithubBranch and
mergeGithubPR currently call JSON.parse(errorBody) on error paths which can
throw and break the documented return contract; update both functions so the
JSON.parse(errorBody) is wrapped in a try-catch and never allowed to throw — on
parse success extract a meaningful message, on failure fall back to using the
raw errorBody or a generic message, then return { ok: false, message } so the
function always returns the documented union; locate the JSON.parse usage in
mergeGithubBranch and mergeGithubPR and implement this guarded parsing behavior.
| * | ||
| * @param request - The incoming Next.js request with the artist_account_id query param. | ||
| * @returns A NextResponse with an error if auth or validation fails, | ||
| * otherwise the validated account ID, artist account ID, and resolved artist slug. |
There was a problem hiding this comment.
Use a Zod-backed validator in this validate*.ts module.
The docs are improved, but the implementation still manually parses artist_account_id instead of validating through a Zod schema with inferred types. Please migrate this validator to the same schema-driven pattern used in other validate*.ts files.
As per coding guidelines lib/**/validate*.ts: “Use Zod for schema validation” and “Export inferred types for validated data”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/content/validateGetContentValidateQuery.ts` around lines 16 - 19, Replace
the manual parsing of artist_account_id in the validateGetContentValidateQuery
module with a Zod-backed validator: define a Zod schema (e.g.,
GetContentQuerySchema) that validates the incoming query shape (including
artist_account_id as the required string/UUID pattern you expect), use
schema.parse or schema.safeParse inside validateGetContentValidateQuery to
validate and extract values, export the inferred type (e.g., type
GetContentQuery = z.infer<typeof GetContentQuerySchema>), and update the
function to return the typed validated data (account ID, artist_account_id,
resolved artist slug) or a NextResponse error on failure; reference the existing
validateGetContentValidateQuery function and export names when making these
changes.
Summary
no-explicit-anywith proper types (unknown, specific interfaces, typed casts)@param, and@returnsto 370+ functions (not empty stubs)Error breakdown (all resolved)
@typescript-eslint/no-explicit-anyjsdoc/require-returnsjsdoc/require-paramjsdoc/require-param-descriptionjsdoc/require-jsdocjsdoc/check-param-namesjsdoc/require-description@typescript-eslint/no-unused-varsjsdoc/tag-linesimport/firstjsdoc/require-hyphen-before-param-description@typescript-eslint/member-orderingTest plan
pnpm lint:checkpasses with 0 errors🤖 Generated with Claude Code
Summary by CodeRabbit
Documentation
Bug Fixes
New Features