agent: @U0AJM7X8FBR API - MPP • actual: using x402 for many endpoints • require#315
agent: @U0AJM7X8FBR API - MPP
• actual: using x402 for many endpoints
• require#315sweetmantech wants to merge 2 commits intotestfrom
Conversation
- Remove @coinbase/x402, x402-fetch, x402-next packages; add mppx
- Upgrade viem to 2.47.5 for mppx Tempo chain compatibility
- Create app/api/mpp/image/generate — MPP-protected image endpoint
using mppx/server tempo.charge() instead of x402 middleware
- Create lib/mpp/{getMppServer, getPayerAddress, fetchWithMppPayment,
getCreditsForPrice, recoup/mppGenerateImage}
- Remove app/api/x402/ routes and lib/x402/ utilities
- Simplify middleware.ts — no longer needs x402 paymentMiddleware
- Update app/api/image/generate to call mppGenerateImage instead of
x402GenerateImage
- New env vars: MPP_SECRET_KEY (HMAC challenge), MPP_PAYMENT_KEY
(private key for Tempo payer account)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
• actual: using x402 for many endpoints • require
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR performs a migration from x402 payment system to MPP (Multi-Protocol Payment), removing x402-related API routes and utility functions while adding new MPP-protected endpoints and payment infrastructure. Additionally, it adds extensive JSDoc parameter documentation across the codebase, introduces an Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant MppEndpoint as MPP Image<br/>Generate Endpoint
participant MppServer as MPP Server
participant ImageGen as Image Generator
participant Arweave as Arweave Storage
participant Database as Database
Client->>MppEndpoint: GET /api/mpp/image/generate<br/>(prompt, files, Authorization)
MppEndpoint->>MppServer: Initialize MPP charge<br/>handleMppCharge()
alt 402 Payment Required
MppServer-->>Client: 402 Challenge
else Payment Accepted
MppEndpoint->>MppEndpoint: Validate prompt & files
alt Invalid Input
MppEndpoint-->>Client: 400 Bad Request
else Valid
MppEndpoint->>ImageGen: generateImage(prompt)
alt Generation Success
ImageGen-->>MppEndpoint: Image Buffer
MppEndpoint->>Arweave: uploadImage(buffer)
Arweave-->>MppEndpoint: Arweave TX ID
MppEndpoint->>Database: createMoment(metadata)
Database-->>MppEndpoint: Moment Record
MppEndpoint-->>Client: 200 JSON<br/>(image data, arweave ID,<br/>moment record, usage)
else Generation Failed
ImageGen-->>MppEndpoint: Error
MppEndpoint-->>Client: 500 Error
end
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 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)
📝 Coding Plan
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: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/api/transcribe/route.ts (1)
11-33:⚠️ Potential issue | 🔴 CriticalDerive account identity from auth context, not request body.
This handler trusts
account_idfrom JSON and does not callvalidateAuthContext(). That allows caller-controlled ownership attribution. Parse body with a Zod validate function, and sourceownerAccountIdfrom authenticated context only.🔧 Suggested patch outline
+const TranscribeRequestSchema = z.object({ + audio_url: z.string().url(), + artist_account_id: z.string().min(1), + title: z.string().optional(), + include_timestamps: z.boolean().optional(), +}); export async function POST(req: NextRequest) { try { - const body = await req.json(); - const { audio_url, account_id, artist_account_id, title, include_timestamps } = body; + const auth = await validateAuthContext(req); + if (auth instanceof NextResponse) return auth; + const parsed = TranscribeRequestSchema.parse(await req.json()); - if (!account_id) { - return NextResponse.json({ error: "Missing required field: account_id" }, { status: 400 }); - } const result = await processAudioTranscription({ - audioUrl: audio_url, - ownerAccountId: account_id, - artistAccountId: artist_account_id, - title, - includeTimestamps: include_timestamps, + audioUrl: parsed.audio_url, + ownerAccountId: auth.accountId, + artistAccountId: parsed.artist_account_id, + title: parsed.title, + includeTimestamps: parsed.include_timestamps, });As per coding guidelines: "Never use
account_idin request bodies or tool schemas; always derive the account ID from authentication", "Always usevalidateAuthContext()for authentication in API routes", and "All API endpoints should use a validate function for input parsing using Zod".🤖 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 11 - 33, Replace trusting account_id from the request body by validating auth and parsing the body with Zod: add a Zod schema to validate the incoming body (audio_url, title, include_timestamps) and use that parsed payload instead of raw req.json(), call validateAuthContext() to get the authenticated account ID and pass that value as ownerAccountId into processAudioTranscription (keep artist_account_id only if it is allowed from body per policy or also derive it if required), and return errors via NextResponse.json as before; ensure validateAuthContext() is invoked before calling processAudioTranscription and remove any use of body.account_id.app/api/image/generate/route.ts (1)
37-42:⚠️ Potential issue | 🟡 MinorAdd response type validation for
mppGenerateImagereturn value.The function returns
Promise<unknown>, and the response flows directly toNextResponse.json()without type checking. Define a response schema (e.g., using Zod) to validate the MPP endpoint's response shape—this ensures the API contracts are enforced and makes the expected structure explicit to future maintainers.Consider:
const mppImageResponseSchema = z.object({ image: z.string(), usage: z.record(z.unknown()), imageUrl: z.string().optional(), arweaveResult: z.unknown().optional(), moment: z.unknown().optional(), arweaveError: z.unknown().optional(), }); const data = await mppGenerateImage(...); const validatedData = mppImageResponseSchema.parse(data); return NextResponse.json(validatedData, { status: 200, headers: getCorsHeaders() });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/image/generate/route.ts` around lines 37 - 42, The route currently forwards the unknown result of mppGenerateImage into NextResponse.json; add a Zod schema (e.g., mppImageResponseSchema) describing the expected shape (image: string, usage: record, optional imageUrl/arweaveResult/moment/arweaveError) and call schema.parse or safeParse on the value returned by mppGenerateImage, then return the validated object to NextResponse.json; on parse failure return a 400 (or appropriate) error response with getCorsHeaders and a clear validation message. Ensure you update route.ts to import zod and reference mppGenerateImage, mppImageResponseSchema, and getCorsHeaders so the contract is enforced before sending the response.
🧹 Nitpick comments (31)
lib/trigger/triggerCreateContent.ts (1)
17-24: LGTM! Clean, single-responsibility function with solid typing.The function adheres well to SOLID principles:
- Single Responsibility: Delegates exclusively to
tasks.triggerfor content task creation- Interface Segregation: The
TriggerCreateContentPayloadinterface is well-documented with property-level JSDocOne minor suggestion: the
@param payloadtag would be slightly more complete with a brief description, e.g.,@param payload - Content creation configuration including account, artist, and template settings. That said, the interface documentation already covers this well, so this is purely optional polish.,
✨ Optional: Enhanced `@param` description
/** * Triggers the create-content task in Trigger.dev. * - * `@param` payload + * `@param` payload - Content creation configuration including account, artist, and template settings */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/trigger/triggerCreateContent.ts` around lines 17 - 24, Update the JSDoc for the triggerCreateContent function to include a brief description for the `@param` tag; specifically, in the JSDoc above triggerCreateContent add something like "@param payload - Content creation configuration including account, artist, and template settings" so the documentation for the payload passed to tasks.trigger(CREATE_CONTENT_TASK_ID, payload) is clearer while leaving the function body (triggerCreateContent) and its use of tasks.trigger unchanged.lib/admins/privy/getCutoffMs.ts (1)
4-10: JSDoc@paramlacks description.Same pattern as other files in this PR—the
@param periodtag is present but provides no additional information beyond what TypeScript types already convey./** * Returns the cutoff timestamp in milliseconds for a given period. * Uses midnight UTC calendar day boundaries to match Privy dashboard behavior. * Returns 0 for "all" (no cutoff). * - * `@param` period + * `@param` period - The time period to calculate the cutoff for (e.g., "7d", "30d", "all") */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/admins/privy/getCutoffMs.ts` around lines 4 - 10, Update the JSDoc for getCutoffMs to include a short description for the `@param` period tag (e.g., explain accepted string values like "day", "week", "month", "all" and that it determines the cutoff window) so the documentation is informative beyond the TypeScript type; edit the comment block above the getCutoffMs function to add this `@param` description and keep it consistent with other files in the PR.lib/catalog/getCatalogSongs.ts (1)
28-34: JSDoc block has multiple@paramtags without descriptions.The added JSDoc provides no additional context beyond what the TypeScript signature already conveys. Consider either completing the documentation or removing the empty
@paramtags:📝 Suggested JSDoc improvement
/** - * - * `@param` catalogId - * `@param` pageSize - * `@param` page - * `@param` artistName + * Fetches a paginated list of songs from a catalog. + * + * `@param` catalogId - The unique identifier of the catalog + * `@param` pageSize - Number of songs per page (default: 100) + * `@param` page - Page number to fetch (default: 1) + * `@param` artistName - Optional filter by artist name + * `@returns` Promise resolving to the catalog songs response with pagination info */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/catalog/getCatalogSongs.ts` around lines 28 - 34, The JSDoc block above the getCatalogSongs function in lib/catalog/getCatalogSongs.ts contains multiple empty `@param` tags; either remove the redundant JSDoc entirely (since TypeScript signatures document parameters) or replace each `@param` with a one-line description matching the parameter purpose (e.g., catalogId: catalog identifier, pageSize: items per page, page: page number, artistName: optional filter) so the comments add real value; update the comment block to reflect the chosen approach and keep it synchronized with the function parameter names.lib/emails/processAndSendEmail.ts (1)
31-39: JSDoc@paramlacks description.The
@param inputtag would benefit from a brief description or a@seereference to theProcessAndSendEmailInputinterface, which is already well-documented via its type definition./** * Shared email processing and sending logic used by both the * POST /api/notifications handler and the send_email MCP tool. * * Handles room lookup, footer generation, markdown-to-HTML conversion, * and the Resend API call. * - * `@param` input + * `@param` input - Email configuration including recipients, subject, and body content */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/emails/processAndSendEmail.ts` around lines 31 - 39, The JSDoc for the processAndSendEmail function has an incomplete `@param` tag; update the comment so the `@param` input includes a brief description or a `@see` reference to the ProcessAndSendEmailInput type (e.g., "@param input - input parameters for processing and sending email. See ProcessAndSendEmailInput for details" or use "@see ProcessAndSendEmailInput") so readers can find the documented interface; locate the JSDoc above the processAndSendEmail function in lib/emails/processAndSendEmail.ts and update the `@param` accordingly.lib/catalog/formatCatalogSongsAsCSV.ts (1)
3-7: JSDoc@paramlacks description.Consider adding a description or removing the bare
@param songstag:/** * Formats catalog songs into the CSV-like format expected by the scorer * - * `@param` songs + * `@param` songs - Array of catalog songs to format into CSV rows */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/catalog/formatCatalogSongsAsCSV.ts` around lines 3 - 7, The JSDoc for the function formatting catalog songs is missing a description for the `@param` tag; update the JSDoc for formatCatalogSongsAsCSV (or the exported function in formatCatalogSongsAsCSV.ts) to either remove the bare "@param songs" tag or replace it with a short description of the parameter (e.g., type/shape of songs and what the function expects) so the docblock fully describes the input; ensure the description matches the function signature and any returned value is documented as well if present.lib/supabase/files/createFileRecord.ts (1)
26-30: JSDoc@paramlacks description.Per coding guidelines, Supabase database functions should follow the documented pattern with complete JSDoc comments. Consider adding a description:
/** * Create a file record in the database * - * `@param` params + * `@param` params - File record parameters including owner, artist, storage key, and metadata + * `@returns` Promise resolving to the created FileRecord + * `@throws` Error if the database insert fails */Based on learnings: "Supabase database functions should import from
@/lib/supabase/serverClientand follow the documented pattern with JSDoc comments, error handling, and return types."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/supabase/files/createFileRecord.ts` around lines 26 - 30, Update the JSDoc for the createFileRecord function to follow the Supabase pattern: add a clear description for the `@param` (describe the params object shape and each property used), add an `@returns` describing the Promise return type (what the resolved value contains), and add an `@throws` (or `@throws`) explaining possible errors; also ensure the module imports the Supabase helper from "@/lib/supabase/serverClient" and that error handling and return types in createFileRecord match the documented pattern.lib/content/validateGetContentEstimateQuery.ts (1)
16-20: JSDoc@paramlacks description.The added
@param requesttag would be more useful with a description explaining its purpose. Consider either completing it or omitting it entirely, since the function signature already makes the parameter's role clear via TypeScript types./** * Validates auth and query params for GET /api/content/estimate. - * - * `@param` request */Or provide a meaningful description:
/** * Validates auth and query params for GET /api/content/estimate. * - * `@param` request + * `@param` request - The incoming Next.js request containing auth headers and query params */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/content/validateGetContentEstimateQuery.ts` around lines 16 - 20, Update the JSDoc for validateGetContentEstimateQuery to either remove the redundant "@param request" tag or add a short descriptive phrase (e.g., "Incoming Express Request object for GET /api/content/estimate containing auth and query parameters") so the comment clarifies the parameter's purpose; modify the JSDoc block above the validateGetContentEstimateQuery function to reflect this change.lib/transcribe/types.ts (1)
56-61: JSDoc@paramlacks description.The
@param errortag would be more informative with a description:/** * Formats transcription errors into user-friendly messages. * Centralizes error message logic to avoid duplication. * - * `@param` error + * `@param` error - The caught error (Error instance or unknown) to format + * `@returns` Object containing user-friendly message and appropriate HTTP status code */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/transcribe/types.ts` around lines 56 - 61, Update the JSDoc for the transcription error formatter to add a clear description for the `@param` error tag: describe that `error` is the Error (or string/unknown) input representing the transcription failure, include expected types (e.g., Error | string | unknown) and what the function does with it (formats into a user-facing message), and optionally note when callers should pass an Error vs a string; reference the existing JSDoc block for the transcription error formatter and the `error` parameter so the comment is explicit and actionable.lib/coding-agent/handleMergeSuccess.ts (1)
6-12: JSDoc@paramlacks description.The existing JSDoc describes the function's behavior well, but the
@param statetag provides no additional context:/** * Handles post-merge cleanup after all PRs merged successfully. * Deletes the shared PR state keys for all repos and persists the latest * snapshot via upsertAccountSnapshot. * - * `@param` state + * `@param` state - The coding agent thread state containing branch, PRs, and snapshot info */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/coding-agent/handleMergeSuccess.ts` around lines 6 - 12, Update the JSDoc for the function handleMergeSuccess to provide a clear description for the `@param` state tag: describe that state is the coding agent's current state object passed into handleMergeSuccess and enumerate the expected pieces used by the function (e.g., accountId or account info, the snapshot object persisted via upsertAccountSnapshot, and any repo/shared PR state keys that will be deleted). Place this description in the existing JSDoc above handleMergeSuccess so someone reading the docs knows what fields the state object must contain.app/api/admins/privy/route.ts (2)
18-20: Empty JSDoc block provides no documentation value.The OPTIONS handler has an empty comment block. Either provide a meaningful description (e.g., "Handles CORS preflight requests") or remove the placeholder entirely.
📝 Proposed fix
-/** - * - */ +/** + * OPTIONS handler for CORS preflight requests. + */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/admins/privy/route.ts` around lines 18 - 20, Remove the empty JSDoc block above the OPTIONS handler in route.ts or replace it with a concise description (e.g., "Handles CORS preflight requests for /api/admins/privy") so the comment either provides meaningful documentation for the OPTIONS handler or is omitted entirely; update the comment adjacent to the OPTIONS handler function export to reflect this change.
11-12: Incomplete@paramtag on GET handler.Add a brief description for the
requestparameter to make the JSDoc useful.📝 Proposed fix
- * - * `@param` request + * `@param` request - The incoming request with optional period query param🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/admins/privy/route.ts` around lines 11 - 12, The JSDoc for the GET handler has an incomplete `@param` tag for the request parameter; update the comment for the GET function (exported async function GET) to include a brief description like "request — the incoming NextRequest object for this handler" (or similar) so the `@param` describes the request parameter's purpose and type.lib/composio/getCallbackUrl.ts (1)
20-23: Redundant@param optionsentry.Lines 20–21 already document
options.destinationandoptions.roomIdwith descriptions. Adding a bare@param optionsafterward is redundant and breaks the conventional JSDoc ordering (parent before children). Remove line 22.📝 Proposed fix
* `@param` options.destination - Where to redirect: "chat" or "connectors" * `@param` options.roomId - For chat destination, the room ID to return to - * `@param` options * `@returns` Full callback URL with success indicator🤖 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 - 23, Remove the redundant JSDoc entry for the whole options object in the getCallbackUrl function's header: delete the bare "@param options" line that follows the documented "@param options.destination" and "@param options.roomId" entries so the JSDoc only lists the parent param (if desired) before or omit it entirely and keep the child params; update the JSDoc block in getCallbackUrl (function name: getCallbackUrl) accordingly to restore correct ordering and avoid duplication.lib/ai/isEmbedModel.ts (1)
6-7: Incomplete@paramtag—add a description.The
@param mlacks context. A brief description clarifies the input expectation.📝 Proposed fix
- * - * `@param` m + * `@param` m - Gateway language model entry to evaluate + * `@returns` True if the model is an embedding model🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/ai/isEmbedModel.ts` around lines 6 - 7, Update the JSDoc for the isEmbedModel function to provide a concise description for the `@param` m tag: explain that m is the model identifier or model object being checked (e.g., "model id string or model descriptor to test for embedding capability") and note expected types/values and that the function returns whether it is an embedding model; update the comment in lib/ai/isEmbedModel.ts so `@param` m clearly documents what callers should pass to isEmbedModel.lib/catalog/getCatalogs.ts (1)
11-14: Incomplete JSDoc—add function and parameter descriptions.The comment block is effectively empty. Document what the function does and what
accountIdrepresents.📝 Proposed fix
/** - * - * `@param` accountId + * Fetches all catalogs associated with the given account. + * + * `@param` accountId - The account identifier to fetch catalogs for + * `@returns` Promise resolving to catalogs response with status and catalog array */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/catalog/getCatalogs.ts` around lines 11 - 14, Add a complete JSDoc for the getCatalogs function: describe that getCatalogs retrieves the list of catalogs (or catalog metadata) for a given account, explain what accountId is (the unique identifier for the account/organization used to scope the query), mention the return value (e.g., Promise resolving to an array of Catalog objects or an empty array) and note any thrown errors or side effects; place this JSDoc immediately above the getCatalogs function declaration and include `@param` {string} accountId and an `@returns` annotation that matches the function's actual return type.lib/transcribe/saveAudioToFiles.ts (1)
5-8: Empty JSDoc provides no value.The added comment block contains only
@param paramswithout any description. Either document whatSaveAudioParamsproperties are expected and what the function does, or remove the empty block—placeholder JSDoc clutters the code without aiding maintainability.📝 Option A: Meaningful documentation
/** - * - * `@param` params + * Uploads an audio blob to storage and creates a corresponding file record. + * + * `@param` params - Audio save parameters including blob, content type, and owner info + * `@returns` The created file record with storage metadata */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/transcribe/saveAudioToFiles.ts` around lines 5 - 8, The JSDoc above saveAudioToFiles is empty and should be replaced with a meaningful doc or removed; update the comment to state what saveAudioToFiles does and document the SaveAudioParams shape (list required properties like fileName, audioBuffer/stream, format, outputDir, any optional flags) and return value (e.g., Promise<void> or paths), or delete the placeholder /** `@param` params */ block entirely if you prefer to keep no JSDoc; reference the saveAudioToFiles function and the SaveAudioParams type when making the change.lib/admins/privy/toMs.ts (1)
4-5: Incomplete@paramtag—add a description.The
@param timestamplacks a description. Since the function handles both seconds and milliseconds formats from Privy, document the expected input to complement the existing context.📝 Proposed fix
- * - * `@param` timestamp + * `@param` timestamp - Privy timestamp (may be in seconds or milliseconds)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/admins/privy/toMs.ts` around lines 4 - 5, Update the JSDoc for the toMs function by adding a clear description to the `@param` timestamp tag stating that timestamp may be a number or string representing either seconds or milliseconds from Privy and that the function will normalize it to milliseconds; reference the toMs function name so the comment is adjacent to its declaration and include examples like "e.g. 1650000000 (seconds) or 1650000000000 (milliseconds) — both normalized to ms".lib/content/validateGetContentValidateQuery.ts (1)
16-17: Incomplete@paramtag—add a description.The
@param requestlacks a description. Briefly note what the request should contain (e.g., auth headers,artist_account_idquery param) to make the documentation actionable.📝 Proposed fix
- * - * `@param` request + * `@param` request - Next.js request with auth headers and artist_account_id query param + * `@returns` Validated query data or NextResponse error🤖 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 - 17, Update the JSDoc for the function (validateGetContentValidateQuery) to complete the `@param` tag for request: describe that request is the incoming HTTP request (e.g., an Express Request) containing authentication headers and the expected query parameter artist_account_id (and any other required query fields), and note the shape/required/optional nature of those fields so callers/readers know what to pass in.lib/transcribe/saveTranscriptToFiles.ts (1)
5-8: JSDoc block is incomplete.The documentation has an empty description and the
@paramtag lacks context. Consider providing meaningful documentation that describes the function's purpose and parameter.📝 Suggested improvement
/** - * - * `@param` params + * Saves a markdown transcript to storage and creates a corresponding file record. + * + * `@param` params - Configuration object containing markdown content, ownership details, and optional metadata */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/transcribe/saveTranscriptToFiles.ts` around lines 5 - 8, Update the JSDoc for the saveTranscriptToFiles function to include a concise description of what the function does and document the params and return value; specifically, replace the empty block with a summary (e.g., "Write transcript data to one or more files") and add `@param` entries describing the "params" object (list its expected properties and types) and an `@returns` tag describing the return type and any thrown errors. Ensure the JSDoc references the saveTranscriptToFiles function and documents any options, file paths, or callbacks contained in the params object so callers know the contract.lib/content/validateCreateContentBody.ts (1)
43-44: JSDoc@paramtag missing description.The
@param requestannotation would benefit from a brief description.📝 Suggested improvement
/** * Validates auth and request body for POST /api/content/create. * - * `@param` request + * `@param` request - The incoming Next.js request object */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/content/validateCreateContentBody.ts` around lines 43 - 44, Add a brief description to the JSDoc `@param` request tag in the validateCreateContentBody function so the purpose of the parameter is clear; locate the JSDoc block above the validateCreateContentBody function in lib/content/validateCreateContentBody.ts and update the `@param` request line with a short phrase like "the incoming HTTP request body to validate" (or equivalent) to document what the parameter represents.lib/catalog/getCatalogDataAsCSV.ts (1)
6-7: JSDoc@paramtag missing description.The
@param catalogIdannotation would be more helpful with a brief description of what the parameter represents.📝 Suggested improvement
/** * Gets all catalog songs and formats them as CSV for the scorer * - * `@param` catalogId + * `@param` catalogId - The unique identifier of the catalog to fetch songs from */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/catalog/getCatalogDataAsCSV.ts` around lines 6 - 7, Add a short descriptive JSDoc for the catalogId parameter on the getCatalogDataAsCSV function: update the JSDoc block above getCatalogDataAsCSV to change the bare "@param catalogId" into something like "@param catalogId - the unique identifier (e.g., UUID or database id) of the catalog to export as CSV" so readers know what value to pass and its purpose; ensure the catalogId symbol and the getCatalogDataAsCSV function name are referenced in the comment.lib/flamingo/getFlamingoPresetsHandler.ts (1)
13-13: JSDoc@paramtag missing description.The
@param requestannotation would be more useful with a description.📝 Suggested improvement
- * `@param` request + * `@param` request - The incoming Next.js request object🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/flamingo/getFlamingoPresetsHandler.ts` at line 13, Update the JSDoc for the getFlamingoPresetsHandler function to add a concise description for the `@param` request tag: describe the shape or purpose of the request parameter (e.g., request object containing query/body/auth fields used by getFlamingoPresetsHandler) so future readers know what is expected and which properties are used.lib/admins/privy/countNewAccounts.ts (1)
8-10: JSDoc@paramtags missing descriptions.Both parameter annotations lack descriptions. Adding context would improve developer experience.
📝 Suggested improvement
/** * Counts how many users in the list were created within the cutoff period. * - * `@param` users - * `@param` period + * `@param` users - Array of Privy user objects to filter + * `@param` period - Time period for the cutoff ("daily", "weekly", or "monthly") */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/admins/privy/countNewAccounts.ts` around lines 8 - 10, Add clear descriptions to the JSDoc `@param` tags for the countNewAccounts function: document what the users parameter is (e.g., array of user objects or specific user type and required fields) and what the period parameter represents (e.g., start/end dates, duration string, or enum) and any expected formats or units; update the JSDoc above countNewAccounts to include those descriptions so IDEs and readers understand expected inputs.lib/admins/privy/getLatestVerifiedAt.ts (1)
5-10: Use account-oriented naming for parameter/docs.Please rename
userto an account-specific name (for example,privyAccount) in both JSDoc and function parameter for terminology consistency.♻️ Suggested rename
- * Returns the most recent latest_verified_at (in ms) across all linked_accounts for a Privy user. + * Returns the most recent latest_verified_at (in ms) across all linked_accounts for a Privy account. ... - * `@param` user + * `@param` privyAccount */ -export function getLatestVerifiedAt(user: User): number | null { - const linkedAccounts = user.linked_accounts; +export function getLatestVerifiedAt(privyAccount: User): number | null { + const linkedAccounts = privyAccount.linked_accounts;As per coding guidelines: "Use 'account' terminology, never 'entity' or 'user'."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/admins/privy/getLatestVerifiedAt.ts` around lines 5 - 10, Rename the parameter and its JSDoc to use account-oriented terminology: change the function signature of getLatestVerifiedAt(user: User) to getLatestVerifiedAt(privyAccount: User) (or another account-specific name like privyAccount) and update the JSDoc `@param` tag and description to reference "account" instead of "user"; ensure all internal references in the function body are updated to the new parameter name to avoid unused/undefined variable errors.lib/content/getArtistContentReadiness.ts (1)
26-29: Replace autogeneratedroot0JSDoc with a meaningful param name.
root0is hard to read in API docs. Preferparamsand keep nested field docs under that name.📝 Suggested JSDoc tweak
- * `@param` root0 - * `@param` root0.accountId - * `@param` root0.artistAccountId - * `@param` root0.artistSlug + * `@param` params + * `@param` params.accountId + * `@param` params.artistAccountId + * `@param` params.artistSlug🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/content/getArtistContentReadiness.ts` around lines 26 - 29, Update the JSDoc for getArtistContentReadiness by replacing the autogenerated "root0" param name with a meaningful "params" (or similar) name used by the function's parameter destructuring, and update the nested `@param` tags to use that root (e.g., `@param` params.accountId, `@param` params.artistAccountId, `@param` params.artistSlug) so the generated API docs are readable and match the function signature.lib/prompts/getSystemPrompt.ts (1)
16-16: Incomplete JSDoc: Missing description fororgIdparameter.Other parameters have descriptions (e.g., "The ID of the room", "The ID of the artist"), but
orgIdlacks one. For consistency:- * `@param` params.orgId + * `@param` params.orgId - The ID of the organization, if applicable.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/prompts/getSystemPrompt.ts` at line 16, The JSDoc for getSystemPrompt is missing a description for the `orgId` parameter; update the JSDoc block in lib/prompts/getSystemPrompt.ts to add a concise description for `orgId` (e.g., "The ID of the organization") so it matches the style of other params and improves documentation for the getSystemPrompt function. Ensure the `@param orgId` line is filled in consistently with the existing param descriptions.lib/mpp/recoup/mppGenerateImage.ts (1)
12-27: Return typePromise<unknown>bypasses type safety.The function returns
Promise<unknown>, forcing callers to handle the response without type guarantees. The calling route (app/api/image/generate/route.ts:37) passes this directly toNextResponse.json(data)without validation.Define an interface for the expected response shape and validate it, or at minimum provide a typed return.
♻️ Add response type and basic validation
+export interface MppGenerateImageResponse { + image: { base64: string; mediaType: string }; + usage: unknown; + imageUrl: string | null; + arweaveResult: unknown | null; + moment: unknown | null; + arweaveError?: string; +} + export async function mppGenerateImage( prompt: string, baseUrl: string, accountId: string, files?: string | null, -): Promise<unknown> { +): Promise<MppGenerateImageResponse> { const mppUrl = new URL("/api/mpp/image/generate", baseUrl); mppUrl.searchParams.set("prompt", prompt); if (files) { mppUrl.searchParams.set("files", files); } const response = await fetchWithMppPayment(mppUrl.toString(), accountId); - return response.json(); + const data = await response.json(); + // Basic validation could be added here with Zod + return data as MppGenerateImageResponse; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/mpp/recoup/mppGenerateImage.ts` around lines 12 - 27, The function mppGenerateImage currently returns Promise<unknown>; define a concrete interface (e.g., MppGenerateImageResponse) that matches the expected API shape and change the function signature to return Promise<MppGenerateImageResponse>; after calling fetchWithMppPayment and before returning, perform basic runtime validation of response.json() (either manual shape checks or via a schema validator like zod) and throw or return a typed error if validation fails so callers (including app/api/image/generate/route.ts which forwards the value to NextResponse.json) receive a correctly typed and validated object.app/api/mpp/image/generate/route.ts (3)
9-9: Module-level initialization may cause startup failures.
getMppServer()is called at module load time. If it throws (e.g., missingMPP_SECRET_KEY), the entire route module fails to load, causing 500 errors for all requests to this endpoint without clear diagnostics.Consider lazy initialization or handling the error gracefully.
♻️ Option: Lazy initialization
-const mppx = getMppServer(); +let mppx: ReturnType<typeof getMppServer> | null = null; + +function getServer() { + if (!mppx) { + mppx = getMppServer(); + } + return mppx; +} export async function GET(request: NextRequest) { try { - const result = await mppx.charge({ amount: "1" })(request); + const server = getServer(); + const result = await server.charge({ amount: "1" })(request);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/mpp/image/generate/route.ts` at line 9, The module currently calls getMppServer() at top-level which can throw and crash the route; remove the module-level invocation and replace it with lazy, safe initialization inside the request handler (or a small cached accessor function) that calls getMppServer() inside a try/catch, caches the resulting instance on success, and returns a controlled error (or null) on failure so the handler can return a proper 4xx/5xx response with diagnostics instead of letting the module fail to load; reference getMppServer() and the route handler in route.ts and ensure the new accessor only invokes getMppServer() once and handles missing MPP_SECRET_KEY or other errors gracefully.
38-50: Manual validation instead of Zod schema.Per coding guidelines, API endpoints should use Zod for input validation. This route performs manual validation for
promptandfilesparameters. Consider using a Zod schema for consistency and better error messages.♻️ Example Zod validation
import { z } from "zod"; const querySchema = z.object({ prompt: z.string().min(1, "prompt query parameter is required"), files: z.string().optional(), }); // In handler: const parsed = querySchema.safeParse({ prompt: searchParams.get("prompt"), files: searchParams.get("files"), }); if (!parsed.success) { return result.withReceipt( NextResponse.json({ error: parsed.error.issues[0].message }, { status: 400, headers: getCorsHeaders() }) ); } const { prompt, files: filesParam } = parsed.data;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/mpp/image/generate/route.ts` around lines 38 - 50, Replace the manual checks around searchParams.get("prompt") and "files" with a Zod-based validator: create a querySchema using z.object({ prompt: z.string().min(1, "prompt query parameter is required"), files: z.string().optional() }), parse the values from searchParams via schema.safeParse, and if parsing fails return the existing result.withReceipt NextResponse.json error using parsed.error.issues[0].message and getCorsHeaders(); on success, pull prompt and filesParam from parsed.data and continue using those variables (keep existing getPayerAddress(request) and result.withReceipt usage).
30-103: Missing test coverage for new endpoint.This is a new API endpoint that handles payment flows and image generation. Based on learnings: "Write tests for new API endpoints covering all success and error paths." Consider adding tests covering:
- Successful image generation with valid MPP credential
- 402 response when payment is required
- 400 responses for missing/invalid prompt and files
- Error paths (generateImage failure, Arweave upload failure)
Would you like me to help generate test cases for this endpoint?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/mpp/image/generate/route.ts` around lines 30 - 103, Add unit/integration tests for the GET handler in app/api/mpp/image/generate/route.ts covering all success and error paths: mock mppx.charge to return a 200 result with withReceipt and a 402 result to assert the challenge path; test missing prompt by calling GET without the prompt query and assert the result.withReceipt returns a 400 JSON error; test invalid files by mocking parseFilesFromQuery to throw and assert 400 JSON error; test successful flow by mocking generateImage to return {image, usage} and uploadImageAndCreateMoment to return {arweaveResult, imageUrl, moment, arweaveError?} and assert the final 200 response contains image/usage/imageUrl/etc.; and add failure paths by mocking generateImage to return no image and uploadImageAndCreateMoment to throw or return an arweaveError and assert proper 500/returned error handling. Ensure tests stub getPayerAddress and getCorsHeaders as needed and verify mppx.charge is invoked with {amount: "1"} and request is passed through.lib/mpp/getPayerAddress.ts (1)
19-24: Missing validation of extracted address format.The function extracts the last segment of the DID (
did:pkh:eip155:<chainId>:<address>) but doesn't validate that it's actually a valid Ethereum address (e.g., starts with0x, correct length). A malformed DID could result in an invalid address being passed to downstream systems likecreateImageMoment.♻️ Add basic address format validation
if (source) { const parts = source.split(":"); - return parts[parts.length - 1] ?? ""; + const address = parts[parts.length - 1]; + // Basic validation: EVM addresses are 42 chars starting with 0x + if (address && /^0x[a-fA-F0-9]{40}$/.test(address)) { + return address; + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/mpp/getPayerAddress.ts` around lines 19 - 24, getPayerAddress currently takes the last segment from the DID stored in variable source but doesn't validate it; update getPayerAddress to validate the extracted address (from parts[parts.length - 1]) against a canonical Ethereum address pattern (e.g. matches /^0x[a-fA-F0-9]{40}$/) and if it fails validation return an empty string (or otherwise sanitize) so downstream callers like createImageMoment never receive a malformed address; keep the existing DID-splitting logic but add this regex check and fallback.lib/mpp/fetchWithMppPayment.ts (1)
15-18: Unsafe type cast of environment variable.The cast
as \0x${string}`at line 16 bypasses TypeScript's type checking. IfMPP_PAYMENT_KEYdoesn't start with0x,privateKeyToAccount` will fail with a cryptic error.♻️ Add format validation
- const paymentKey = process.env.MPP_PAYMENT_KEY as `0x${string}`; - if (!paymentKey) { + const paymentKey = process.env.MPP_PAYMENT_KEY; + if (!paymentKey || !paymentKey.startsWith("0x")) { throw new Error("MPP_PAYMENT_KEY environment variable is required"); + throw new Error("MPP_PAYMENT_KEY must be a valid hex string starting with 0x"); } + const validatedKey = paymentKey as `0x${string}`;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/mpp/fetchWithMppPayment.ts` around lines 15 - 18, The function fetchWithMppPayment currently unsafely casts process.env.MPP_PAYMENT_KEY to `0x${string}` which can hide malformed keys and cause privateKeyToAccount to throw; remove the cast and validate the environment value inside fetchWithMppPayment (read it as string|undefined), check it matches the expected hex format (e.g. startsWith('0x') and matches /^0x[0-9a-fA-F]{64}$/ or your project's expected length), and throw a clear Error like "MPP_PAYMENT_KEY must be a 0x-prefixed 64-hex-char private key" if validation fails before calling privateKeyToAccount or using paymentKey. Ensure you reference the paymentKey variable and privateKeyToAccount call so the validation is applied immediately before usage.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6d79ca86-bbcb-4338-8209-739dfa014403
⛔ Files ignored due to path filters (66)
lib/admins/emails/__tests__/validateGetAdminEmailsQuery.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/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/artists/__tests__/buildGetArtistsParams.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/artists/__tests__/checkAccountArtistAccess.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/artists/__tests__/createArtistInDb.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/artists/__tests__/validateGetArtistsRequest.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__/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__/setupConversation.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chat/__tests__/setupToolsForRequest.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__/getPrepareStepResult.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chats/__tests__/updateChatHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/chats/__tests__/validateUpdateChatBody.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__/onMergeTestToMainAction.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/credits/__tests__/handleChatCredits.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__/deleteAccountGithubRepos.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/__tests__/getMcpTools.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/mcp/__tests__/verifyApiKey.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/messages/__tests__/convertToUiMessages.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/organizations/__tests__/canAccessAccount.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/organizations/__tests__/validateOrganizationAccess.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/pulse/__tests__/buildGetPulsesParams.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/pulse/__tests__/getPulsesHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/pulse/__tests__/updatePulsesHandler.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/pulse/__tests__/validateGetPulsesRequest.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/rooms/__tests__/copyRoom.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/account_artist_ids/__tests__/insertAccountArtistId.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/account_artist_ids/__tests__/selectAccountArtistId.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/account_organization_ids/__tests__/selectAccountOrganizationIds.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/account_sandboxes/__tests__/insertAccountSandbox.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/account_workspace_ids/__tests__/selectAccountWorkspaceId.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/accounts/__tests__/selectAccountWithSocials.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/artist_organization_ids/__tests__/selectArtistOrganizationIds.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/pulse_accounts/__tests__/selectPulseAccounts.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/supabase/pulse_accounts/__tests__/upsertPulseAccount.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/tasks/__tests__/deleteTask.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/**middleware.tsis excluded by none and included by nonepackage.jsonis excluded by none and included by nonepnpm-lock.yamlis excluded by!**/pnpm-lock.yamland included by none
📒 Files selected for processing (69)
app/api/accounts/[id]/route.tsapp/api/admins/privy/route.tsapp/api/coding-agent/[platform]/route.tsapp/api/image/generate/route.tsapp/api/mpp/image/generate/route.tsapp/api/songs/analyze/presets/route.tsapp/api/transcribe/route.tsapp/api/x402/image/generate/route.tsapp/api/x402/session-token/route.tslib/admins/privy/countNewAccounts.tslib/admins/privy/fetchPrivyLogins.tslib/admins/privy/getCutoffMs.tslib/admins/privy/getLatestVerifiedAt.tslib/admins/privy/toMs.tslib/ai/getModel.tslib/ai/isEmbedModel.tslib/catalog/formatCatalogSongsAsCSV.tslib/catalog/getCatalogDataAsCSV.tslib/catalog/getCatalogSongs.tslib/catalog/getCatalogs.tslib/chat/toolChains/getPrepareStepResult.tslib/chats/processCompactChatRequest.tslib/coding-agent/encodeGitHubThreadId.tslib/coding-agent/handleMergeSuccess.tslib/coding-agent/parseMergeActionId.tslib/coding-agent/parseMergeTestToMainActionId.tslib/composio/getCallbackUrl.tslib/content/contentTemplates.tslib/content/createContentHandler.tslib/content/getArtistContentReadiness.tslib/content/getArtistFileTree.tslib/content/getArtistRootPrefix.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/github/expandSubmoduleEntries.tslib/github/getRepoGitModules.tslib/github/resolveSubmodulePath.tslib/mcp/resolveAccountId.tslib/mcp/tools/transcribe/registerTranscribeAudioTool.tslib/mpp/fetchWithMppPayment.tslib/mpp/getCreditsForPrice.tslib/mpp/getMppServer.tslib/mpp/getPayerAddress.tslib/mpp/recoup/mppGenerateImage.tslib/prompts/getSystemPrompt.tslib/spotify/getSpotifyFollowers.tslib/supabase/account_artist_ids/getAccountArtistIds.tslib/supabase/account_workspace_ids/getAccountWorkspaceIds.tslib/supabase/files/createFileRecord.tslib/supabase/song_artists/insertSongArtists.tslib/supabase/storage/uploadFileByKey.tslib/transcribe/processAudioTranscription.tslib/transcribe/saveAudioToFiles.tslib/transcribe/saveTranscriptToFiles.tslib/transcribe/types.tslib/trigger/triggerCreateContent.tslib/x402/fetchWithPayment.tslib/x402/getBuyerAccount.tslib/x402/getTransferCalls.tslib/x402/loadAccount.tslib/x402/recoup/x402GenerateImage.ts
💤 Files with no reviewable changes (7)
- lib/x402/getBuyerAccount.ts
- lib/x402/recoup/x402GenerateImage.ts
- app/api/x402/image/generate/route.ts
- lib/x402/getTransferCalls.ts
- lib/x402/fetchWithPayment.ts
- app/api/x402/session-token/route.ts
- lib/x402/loadAccount.ts
| * @param request - The request object | ||
| * @param params.params | ||
| * @param params - Route params containing the account ID |
There was a problem hiding this comment.
Incorrect and redundant @param entry.
Line 26 adds @param params.params which is malformed—there's no params.params in the function signature. The existing line 27 already documents the params parameter correctly. Remove the erroneous line.
📝 Proposed fix
* `@param` request - The request object
- * `@param` params.params
* `@param` params - Route params containing the account ID📝 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 request - The request object | |
| * @param params.params | |
| * @param params - Route params containing the account ID | |
| * `@param` request - The request object | |
| * `@param` params - Route params containing the account ID |
🤖 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 25 - 27, Remove the malformed
JSDoc entry "@param params.params" from the comment block above the account
route handler (the doc that currently lists "@param request" and "@param
params"); the function signature only has "params" so keep the correct "@param
params - Route params containing the account ID" line and delete the
redundant/malformed "@param params.params" line so the JSDoc matches the
handler's parameters.
| * @param request - The incoming verification request | ||
| * @param params.params | ||
| * @param params - Route params containing the platform name |
There was a problem hiding this comment.
Remove duplicate/incorrect @param entry.
The @param params.params on line 13 is syntactically incorrect and redundant—@param params on line 14 already documents the route parameters. This appears to be an erroneous addition.
🧹 Suggested fix
* `@param` request - The incoming verification request
- * `@param` params.params
* `@param` params - Route params containing the platform name📝 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 request - The incoming verification request | |
| * @param params.params | |
| * @param params - Route params containing the platform name | |
| * `@param` request - The incoming verification request | |
| * `@param` params - Route params containing the platform name |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/api/coding-agent/`[platform]/route.ts around lines 12 - 14, Remove the
erroneous duplicate JSDoc param entry by deleting the incorrect "@param
params.params" line in the route handler's comment block (the one documenting
the function that takes request and params); keep the correct "@param request"
and "@param params" entries so the route.ts JSDoc documents the incoming
verification request and the route params consistently.
| * @param request - The incoming webhook request | ||
| * @param params.params | ||
| * @param params - Route params containing the platform name |
There was a problem hiding this comment.
Same issue: remove duplicate/incorrect @param entry.
The @param params.params on line 38 should be removed for the same reason as above.
🧹 Suggested fix
* `@param` request - The incoming webhook request
- * `@param` params.params
* `@param` params - Route params containing the platform name📝 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 request - The incoming webhook request | |
| * @param params.params | |
| * @param params - Route params containing the platform name | |
| * `@param` request - The incoming webhook request | |
| * `@param` params - Route params containing the platform name |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/api/coding-agent/`[platform]/route.ts around lines 37 - 39, Remove the
duplicate/incorrect JSDoc entry "@param params.params" from the route handler's
comment block in app/api/coding-agent/[platform]/route.ts; keep the single
correct "@param params - Route params containing the platform name" line and
ensure the JSDoc only documents the actual parameters used by the exported route
function (e.g., the request and params objects referenced in the route handler).
| const { searchParams } = new URL(request.url); | ||
| const prompt = searchParams.get("prompt"); | ||
| const filesParam = searchParams.get("files"); | ||
| const account = getPayerAddress(request); |
There was a problem hiding this comment.
Payer address not validated after extraction.
getPayerAddress(request) can return an empty string if the Authorization header is missing or malformed. This empty string is passed to uploadImageAndCreateMoment, which silently skips moment creation (see lib/arweave/uploadImageAndCreateMoment.ts:48). Payment attribution is lost without any indication.
🛡️ Add validation for account
const account = getPayerAddress(request);
+ if (!account) {
+ return result.withReceipt(
+ NextResponse.json(
+ { error: "Could not extract payer address from Authorization header" },
+ { status: 401, headers: getCorsHeaders() },
+ ),
+ );
+ }
+
if (!prompt) {📝 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.
| const account = getPayerAddress(request); | |
| const account = getPayerAddress(request); | |
| if (!account) { | |
| return result.withReceipt( | |
| NextResponse.json( | |
| { error: "Could not extract payer address from Authorization header" }, | |
| { status: 401, headers: getCorsHeaders() }, | |
| ), | |
| ); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/api/mpp/image/generate/route.ts` at line 41, The extracted payer address
from getPayerAddress(request) can be an empty string and should be validated
before calling uploadImageAndCreateMoment; update the handler in route.ts to
check the returned account (from getPayerAddress) and if it's falsy/empty,
return a 400/unauthorized response (or throw an appropriate error) with a clear
message instead of passing the empty string into uploadImageAndCreateMoment;
reference the variables/function names getPayerAddress, account, and
uploadImageAndCreateMoment so the check is added immediately after const account
= getPayerAddress(request).
| const { image, usage } = await generateImage(prompt, files); | ||
|
|
||
| if (!image) { | ||
| return result.withReceipt( | ||
| NextResponse.json( | ||
| { error: "Failed to generate image" }, | ||
| { status: 500, headers: getCorsHeaders() }, | ||
| ), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Destructuring before null check causes potential runtime error.
Line 68 destructures { image, usage } from generateImage(prompt, files), but generateImage can return null (per lib/ai/generateImage.ts). The null check at line 70 happens after destructuring, which would throw a TypeError if generateImage returns null.
🐛 Proposed fix
- const { image, usage } = await generateImage(prompt, files);
+ const result = await generateImage(prompt, files);
- if (!image) {
+ if (!result) {
return result.withReceipt(
NextResponse.json(
{ error: "Failed to generate image" },
{ status: 500, headers: getCorsHeaders() },
),
);
}
+ const { image, usage } = result;
+
const {📝 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.
| const { image, usage } = await generateImage(prompt, files); | |
| if (!image) { | |
| return result.withReceipt( | |
| NextResponse.json( | |
| { error: "Failed to generate image" }, | |
| { status: 500, headers: getCorsHeaders() }, | |
| ), | |
| ); | |
| } | |
| const imageResponse = await generateImage(prompt, files); | |
| if (!imageResponse) { | |
| return result.withReceipt( | |
| NextResponse.json( | |
| { error: "Failed to generate image" }, | |
| { status: 500, headers: getCorsHeaders() }, | |
| ), | |
| ); | |
| } | |
| const { image, usage } = imageResponse; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/api/mpp/image/generate/route.ts` around lines 68 - 77, The code
destructures { image, usage } directly from generateImage(prompt, files) but
generateImage can return null, causing a TypeError; change the flow to first
assign the raw result (e.g., const genResult = await generateImage(prompt,
files)), check if genResult is null and handle the error via
result.withReceipt/NextResponse.json with getCorsHeaders, then safely extract
genResult.image and genResult.usage (or destructure after the null check) and
continue.
| const creditsToDeduct = getCreditsForPrice(IMAGE_GENERATE_PRICE); | ||
| await deductCredits({ accountId, creditsToDeduct }); | ||
|
|
||
| const account = privateKeyToAccount(paymentKey); | ||
| const mppx = Mppx.create({ | ||
| methods: [tempo({ account })], | ||
| polyfill: false, | ||
| }); | ||
|
|
||
| return mppx.fetch(url, { method: "GET" }); |
There was a problem hiding this comment.
Credits deducted before fetch with no rollback on failure.
Credits are deducted at line 22 before mppx.fetch executes at line 30. If the fetch fails (network error, server error, etc.), the user loses credits without receiving the service. According to lib/credits/deductCredits.ts, there's no built-in rollback mechanism.
Consider wrapping in a try-catch with credit restoration on failure, or deferring deduction until after confirmed success.
🛡️ Proposed fix with rollback on failure
+import { restoreCredits } from "@/lib/credits/restoreCredits";
+
export async function fetchWithMppPayment(url: string, accountId: string): Promise<Response> {
const paymentKey = process.env.MPP_PAYMENT_KEY as `0x${string}`;
if (!paymentKey) {
throw new Error("MPP_PAYMENT_KEY environment variable is required");
}
const creditsToDeduct = getCreditsForPrice(IMAGE_GENERATE_PRICE);
await deductCredits({ accountId, creditsToDeduct });
const account = privateKeyToAccount(paymentKey);
const mppx = Mppx.create({
methods: [tempo({ account })],
polyfill: false,
});
- return mppx.fetch(url, { method: "GET" });
+ try {
+ return await mppx.fetch(url, { method: "GET" });
+ } catch (error) {
+ // Restore credits on fetch failure
+ await restoreCredits({ accountId, creditsToRestore: creditsToDeduct });
+ throw error;
+ }
}Note: You'll need to implement restoreCredits or use an existing mechanism.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/mpp/fetchWithMppPayment.ts` around lines 21 - 30, Credits are being
deducted before the MPP fetch so users lose credits if mppx.fetch fails; modify
the flow in fetchWithMppPayment by either deferring calling deductCredits({
accountId, creditsToDeduct }) until after mppx.fetch succeeds, or wrap the
mppx.fetch call in a try-catch and call a restoreCredits(accountId,
creditsToDeduct) on any failure; locate the code around
getCreditsForPrice(IMAGE_GENERATE_PRICE), deductCredits, privateKeyToAccount,
Mppx.create and mppx.fetch and implement the chosen rollback/defer approach
(ensure restoreCredits exists or add it) so credits are only final on successful
fetch.
| export function getMppServer() { | ||
| return Mppx.create({ | ||
| methods: [ | ||
| tempo({ | ||
| recipient: SMART_ACCOUNT_ADDRESS, | ||
| }), | ||
| ], | ||
| secretKey: process.env.MPP_SECRET_KEY, | ||
| }); |
There was a problem hiding this comment.
Missing validation for MPP_SECRET_KEY environment variable.
Unlike fetchWithMppPayment.ts which validates MPP_PAYMENT_KEY and throws a descriptive error if missing, this function passes process.env.MPP_SECRET_KEY directly to Mppx.create without validation. If the variable is unset, this could cause cryptic failures downstream.
🛡️ Proposed fix to add validation
export function getMppServer() {
+ const secretKey = process.env.MPP_SECRET_KEY;
+ if (!secretKey) {
+ throw new Error("MPP_SECRET_KEY environment variable is required");
+ }
+
return Mppx.create({
methods: [
tempo({
recipient: SMART_ACCOUNT_ADDRESS,
}),
],
- secretKey: process.env.MPP_SECRET_KEY,
+ secretKey,
});
}📝 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.
| export function getMppServer() { | |
| return Mppx.create({ | |
| methods: [ | |
| tempo({ | |
| recipient: SMART_ACCOUNT_ADDRESS, | |
| }), | |
| ], | |
| secretKey: process.env.MPP_SECRET_KEY, | |
| }); | |
| export function getMppServer() { | |
| const secretKey = process.env.MPP_SECRET_KEY; | |
| if (!secretKey) { | |
| throw new Error("MPP_SECRET_KEY environment variable is required"); | |
| } | |
| return Mppx.create({ | |
| methods: [ | |
| tempo({ | |
| recipient: SMART_ACCOUNT_ADDRESS, | |
| }), | |
| ], | |
| secretKey, | |
| }); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/mpp/getMppServer.ts` around lines 10 - 18, getMppServer currently passes
process.env.MPP_SECRET_KEY straight into Mppx.create without verifying it; add a
validation step at the start of getMppServer to check process.env.MPP_SECRET_KEY
and throw a clear, descriptive error if it's missing (matching the pattern used
in fetchWithMppPayment.ts), then pass the validated value to Mppx.create
(referencing the getMppServer function, MPP_SECRET_KEY env var, and
Mppx.create).
| export function getPayerAddress(request: NextRequest): string { | ||
| const authHeader = request.headers.get("Authorization"); | ||
| if (!authHeader) return ""; | ||
| try { | ||
| // The MPP credential is base64-encoded JSON in the Authorization header | ||
| // Format: "Payment <base64>" | ||
| const base64 = authHeader.replace(/^Payment\s+/i, ""); | ||
| const decoded = Buffer.from(base64, "base64").toString("utf-8"); | ||
| const credential = JSON.parse(decoded); | ||
| // source is a DID: "did:pkh:eip155:4217:0x..." | ||
| const source: string = credential?.source ?? ""; | ||
| if (source) { | ||
| const parts = source.split(":"); | ||
| return parts[parts.length - 1] ?? ""; | ||
| } | ||
| } catch { | ||
| // ignore parse errors | ||
| } | ||
| return ""; |
There was a problem hiding this comment.
Silent failure pattern may cause undetected payment attribution loss.
Returning an empty string on parsing failures creates a silent failure path. According to the context in app/api/mpp/image/generate/route.ts:41, getPayerAddress(request) is called but never validated. When extraction fails:
uploadImageAndCreateMomentsilently skips moment creation (seelib/arweave/uploadImageAndCreateMoment.ts:48)- Payment attribution via
createImageMomentis lost without any indication
Consider either:
- Throwing an error for invalid/missing credentials (fail-fast)
- Returning
nullinstead of""to make the failure state explicit and type-checkable - Adding validation in the calling route
🛡️ Option 1: Return null for explicit failure state
-export function getPayerAddress(request: NextRequest): string {
+export function getPayerAddress(request: NextRequest): string | null {
const authHeader = request.headers.get("Authorization");
- if (!authHeader) return "";
+ if (!authHeader) return null;
try {
const base64 = authHeader.replace(/^Payment\s+/i, "");
const decoded = Buffer.from(base64, "base64").toString("utf-8");
const credential = JSON.parse(decoded);
const source: string = credential?.source ?? "";
if (source) {
const parts = source.split(":");
- return parts[parts.length - 1] ?? "";
+ return parts[parts.length - 1] || null;
}
} catch {
// ignore parse errors
}
- return "";
+ return null;
}📝 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.
| export function getPayerAddress(request: NextRequest): string { | |
| const authHeader = request.headers.get("Authorization"); | |
| if (!authHeader) return ""; | |
| try { | |
| // The MPP credential is base64-encoded JSON in the Authorization header | |
| // Format: "Payment <base64>" | |
| const base64 = authHeader.replace(/^Payment\s+/i, ""); | |
| const decoded = Buffer.from(base64, "base64").toString("utf-8"); | |
| const credential = JSON.parse(decoded); | |
| // source is a DID: "did:pkh:eip155:4217:0x..." | |
| const source: string = credential?.source ?? ""; | |
| if (source) { | |
| const parts = source.split(":"); | |
| return parts[parts.length - 1] ?? ""; | |
| } | |
| } catch { | |
| // ignore parse errors | |
| } | |
| return ""; | |
| export function getPayerAddress(request: NextRequest): string | null { | |
| const authHeader = request.headers.get("Authorization"); | |
| if (!authHeader) return null; | |
| try { | |
| // The MPP credential is base64-encoded JSON in the Authorization header | |
| // Format: "Payment <base64>" | |
| const base64 = authHeader.replace(/^Payment\s+/i, ""); | |
| const decoded = Buffer.from(base64, "base64").toString("utf-8"); | |
| const credential = JSON.parse(decoded); | |
| // source is a DID: "did:pkh:eip155:4217:0x..." | |
| const source: string = credential?.source ?? ""; | |
| if (source) { | |
| const parts = source.split(":"); | |
| return parts[parts.length - 1] || null; | |
| } | |
| } catch { | |
| // ignore parse errors | |
| } | |
| return null; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/mpp/getPayerAddress.ts` around lines 10 - 28, Change getPayerAddress to
return an explicit failure value (null) instead of an empty string and update
its signature to return string | null so callers can detect parse failures;
inside getPayerAddress (function name) keep the same parsing logic but return
null on missing Authorization or JSON/parse errors rather than ""; then update
the callers (the route that calls getPayerAddress in
app/api/mpp/image/generate/route.ts and uploadImageAndCreateMoment /
createImageMoment usages in lib/arweave/uploadImageAndCreateMoment.ts) to
validate for null and either fail-fast (throw/return an error response) or
handle attribution absence explicitly. Ensure tests/type checks are updated to
reflect the new return type.
| const response = await fetchWithMppPayment(mppUrl.toString(), accountId); | ||
| return response.json(); |
There was a problem hiding this comment.
Missing error handling for non-OK responses.
The function assumes fetchWithMppPayment always returns a successful response. If the MPP endpoint returns a 4xx/5xx status, response.json() may fail or return an error object that doesn't match expected shape.
🛡️ Add response status check
const response = await fetchWithMppPayment(mppUrl.toString(), accountId);
+ if (!response.ok) {
+ const errorBody = await response.text();
+ throw new Error(`MPP image generation failed: ${response.status} - ${errorBody}`);
+ }
return response.json();
}📝 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.
| const response = await fetchWithMppPayment(mppUrl.toString(), accountId); | |
| return response.json(); | |
| const response = await fetchWithMppPayment(mppUrl.toString(), accountId); | |
| if (!response.ok) { | |
| const errorBody = await response.text(); | |
| throw new Error(`MPP image generation failed: ${response.status} - ${errorBody}`); | |
| } | |
| return response.json(); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/mpp/recoup/mppGenerateImage.ts` around lines 25 - 26, The function
mppGenerateImage currently calls fetchWithMppPayment and directly returns
response.json() without checking HTTP status; update it to check response.ok (or
response.status) after the fetchWithMppPayment call and handle non-2xx responses
by parsing the error body (e.g., await response.text() or response.json()) and
throwing or returning a structured error; ensure callers of mppGenerateImage
receive a consistent error shape. Locate the call site using the symbol
fetchWithMppPayment and the surrounding function (mppGenerateImage) to add the
status check and error handling before returning the JSON.
| * @param songArtists | ||
| */ |
There was a problem hiding this comment.
Complete the @param JSDoc description.
@param songArtists is currently undocumented; add a short description so the contract is explicit for callers and tooling.
Suggested update
/**
* Inserts song-artist relationships, skipping duplicates.
*
- * `@param` songArtists
+ * `@param` songArtists Array of song-artist join rows to validate, deduplicate, and upsert.
*/As per coding guidelines: lib/supabase/**/*.ts functions should follow the documented pattern with JSDoc comments.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/supabase/song_artists/insertSongArtists.ts` around lines 9 - 10, Add a
short JSDoc description for the `songArtists` parameter on the
`insertSongArtists` function: describe that `songArtists` is the array (or
single item if applicable) of SongArtist records/objects to be inserted into the
song_artists table (include expected shape or model name, e.g., SongArtist or
Partial<SongArtist>), and note whether it may be empty/null and how the function
handles that; update the `@param songArtists` line to a one-sentence description
following the existing JSDoc style used in lib/supabase files.
Automated PR from coding agent.
Prompt: @U0AJM7X8FBR API - MPP
• actual: using x402 for many endpoints
• required: replace those x402 endpoints with MPP
• follow these docs: https://mpp.dev/overview
Summary by CodeRabbit
New Features
Refactor
Documentation