Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/api/accounts/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export async function OPTIONS() {
* - id (required): The unique identifier of the account (UUID)
*
* @param request - The request object
* @param params.params
* @param params - Route params containing the account ID
Comment on lines 25 to 27
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
* @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.

* @returns A NextResponse with account data
*/
Expand Down
5 changes: 5 additions & 0 deletions app/api/admins/privy/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ import { getPrivyLoginsHandler } from "@/lib/admins/privy/getPrivyLoginsHandler"
* Returns Privy login statistics for the requested time period.
* Supports daily (last 24h), weekly (last 7 days), and monthly (last 30 days) periods.
* Requires admin authentication.
*
* @param request
*/
export async function GET(request: NextRequest): Promise<NextResponse> {
return getPrivyLoginsHandler(request);
}

/**
*
*/
export async function OPTIONS(): Promise<NextResponse> {
return new NextResponse(null, { status: 204, headers: getCorsHeaders() });
}
2 changes: 2 additions & 0 deletions app/api/coding-agent/[platform]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "@/lib/coding-agent/handlers/registerHandlers";
* Handles webhook verification handshakes (e.g. WhatsApp hub.challenge).
*
* @param request - The incoming verification request
* @param params.params
* @param params - Route params containing the platform name
Comment on lines 12 to 14
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
* @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.

*/
export async function GET(
Expand All @@ -34,6 +35,7 @@ export async function GET(
* Handles Slack and WhatsApp webhooks via dynamic [platform] segment.
*
* @param request - The incoming webhook request
* @param params.params
* @param params - Route params containing the platform name
Comment on lines 37 to 39
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
* @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).

*/
export async function POST(
Expand Down
6 changes: 3 additions & 3 deletions app/api/image/generate/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { getCorsHeaders } from "@/lib/networking/getCorsHeaders";
import { x402GenerateImage } from "@/lib/x402/recoup/x402GenerateImage";
import { mppGenerateImage } from "@/lib/mpp/recoup/mppGenerateImage";
import { validateGenerateImageQuery } from "@/lib/image/validateGenerateImageQuery";

/**
Expand All @@ -17,7 +17,7 @@ export async function OPTIONS() {

/**
* GET handler for image generation endpoint.
* Accepts prompt and account_id, and fetches from the x402-protected endpoint.
* Accepts prompt and account_id, and fetches from the MPP-protected endpoint.
*
* @param request - The request object containing query parameters.
* @returns {Promise<NextResponse>} JSON response matching the Recoup API format.
Expand All @@ -34,7 +34,7 @@ export async function GET(request: NextRequest) {
const files = searchParams.get("files");

const baseUrl = request.nextUrl.origin;
const data = await x402GenerateImage(prompt, baseUrl, account_id, files);
const data = await mppGenerateImage(prompt, baseUrl, account_id, files);

return NextResponse.json(data, {
status: 200,
Expand Down
104 changes: 104 additions & 0 deletions app/api/mpp/image/generate/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { NextRequest, NextResponse } from "next/server";
import generateImage from "@/lib/ai/generateImage";
import { getCorsHeaders } from "@/lib/networking/getCorsHeaders";
import { uploadImageAndCreateMoment } from "@/lib/arweave/uploadImageAndCreateMoment";
import { getPayerAddress } from "@/lib/mpp/getPayerAddress";
import { parseFilesFromQuery } from "@/lib/files/parseFilesFromQuery";
import { getMppServer } from "@/lib/mpp/getMppServer";

const mppx = getMppServer();

/**
* OPTIONS handler for CORS preflight requests.
*
* @returns A NextResponse with CORS headers.
*/
export async function OPTIONS() {
return new NextResponse(null, {
status: 200,
headers: getCorsHeaders(),
});
}

/**
* GET handler for image generation endpoint (MPP protected).
* Requires a valid MPP payment credential via the Authorization header.
*
* @param request - The request object containing query parameters.
* @returns {Promise<NextResponse>} JSON response with generated image data or error.
*/
export async function GET(request: NextRequest) {
try {
const result = await mppx.charge({ amount: "1" })(request);

if (result.status === 402) {
return result.challenge;
}

const { searchParams } = new URL(request.url);
const prompt = searchParams.get("prompt");
const filesParam = searchParams.get("files");
const account = getPayerAddress(request);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

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.

Suggested change
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).


if (!prompt) {
return result.withReceipt(
NextResponse.json(
{ error: "prompt query parameter is required" },
{ status: 400, headers: getCorsHeaders() },
),
);
}

let files;
try {
files = parseFilesFromQuery(filesParam);
} catch (error) {
return result.withReceipt(
NextResponse.json(
{
error: "Invalid files parameter.",
details:
error instanceof Error ? error.message : "Format must be: url1:type1|url2:type2",
},
{ status: 400, headers: getCorsHeaders() },
),
);
}

const { image, usage } = await generateImage(prompt, files);

if (!image) {
return result.withReceipt(
NextResponse.json(
{ error: "Failed to generate image" },
{ status: 500, headers: getCorsHeaders() },
),
);
}
Comment on lines +68 to +77
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

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.

Suggested change
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 {
arweaveResult,
imageUrl,
moment: momentResult,
arweaveError,
} = await uploadImageAndCreateMoment({ image, prompt, account });

return result.withReceipt(
NextResponse.json(
{
image,
usage,
imageUrl,
arweaveResult,
moment: momentResult,
...(arweaveError && { arweaveError }),
},
{ status: 200, headers: getCorsHeaders() },
),
);
} catch (error) {
console.error("Error in MPP image generation endpoint:", error);
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
return NextResponse.json({ error: errorMessage }, { status: 500, headers: getCorsHeaders() });
}
}
1 change: 1 addition & 0 deletions app/api/songs/analyze/presets/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export async function OPTIONS() {
* - status: "success"
* - presets: Array of { name, label, description, requiresAudio, responseFormat }
*
* @param request
* @returns A NextResponse with the list of available presets
*/
export async function GET(request: NextRequest): Promise<NextResponse> {
Expand Down
4 changes: 4 additions & 0 deletions app/api/transcribe/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { NextRequest, NextResponse } from "next/server";
import { processAudioTranscription } from "@/lib/transcribe/processAudioTranscription";
import { formatTranscriptionError } from "@/lib/transcribe/types";

/**
*
* @param req
*/
export async function POST(req: NextRequest) {
try {
const body = await req.json();
Expand Down
112 changes: 0 additions & 112 deletions app/api/x402/image/generate/route.ts

This file was deleted.

1 change: 0 additions & 1 deletion app/api/x402/session-token/route.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ vi.mock("@/lib/admins/validateAdminAuth", () => ({
validateAdminAuth: vi.fn(),
}));

/**
*
* @param url
*/
function createMockRequest(url: string): NextRequest {
return {
url,
Expand Down
10 changes: 7 additions & 3 deletions lib/admins/privy/__tests__/getPrivyLoginsHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest, NextResponse } from "next/server";
import { getPrivyLoginsHandler } from "../getPrivyLoginsHandler";

import { validateGetPrivyLoginsQuery } from "../validateGetPrivyLoginsQuery";
import { fetchPrivyLogins } from "../fetchPrivyLogins";

vi.mock("@/lib/networking/getCorsHeaders", () => ({
getCorsHeaders: vi.fn(() => ({ "Access-Control-Allow-Origin": "*" })),
}));
Expand All @@ -14,9 +17,6 @@ vi.mock("../fetchPrivyLogins", () => ({
fetchPrivyLogins: vi.fn(),
}));

import { validateGetPrivyLoginsQuery } from "../validateGetPrivyLoginsQuery";
import { fetchPrivyLogins } from "../fetchPrivyLogins";

const now = Date.now();
const ONE_HOUR_AGO = Math.floor((now - 60 * 60 * 1000) / 1000);
const TWO_HOURS_AGO = Math.floor((now - 2 * 60 * 60 * 1000) / 1000);
Expand All @@ -42,6 +42,10 @@ const mockLogins = [
},
];

/**
*
* @param period
*/
function makeRequest(period = "daily") {
return new NextRequest(`https://example.com/api/admins/privy?period=${period}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest, NextResponse } from "next/server";
import { validateGetPrivyLoginsQuery } from "../validateGetPrivyLoginsQuery";

import { validateAdminAuth } from "@/lib/admins/validateAdminAuth";

vi.mock("@/lib/networking/getCorsHeaders", () => ({
getCorsHeaders: vi.fn(() => ({ "Access-Control-Allow-Origin": "*" })),
}));
Expand All @@ -10,10 +12,12 @@ vi.mock("@/lib/admins/validateAdminAuth", () => ({
validateAdminAuth: vi.fn(),
}));

import { validateAdminAuth } from "@/lib/admins/validateAdminAuth";

const mockAuth = { accountId: "test-account", orgId: null, authToken: "token" };

/**
*
* @param period
*/
function makeRequest(period?: string) {
const url = period
? `https://example.com/api/admins/privy?period=${period}`
Expand Down
3 changes: 3 additions & 0 deletions lib/admins/privy/countNewAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { getCutoffMs } from "./getCutoffMs";

/**
* Counts how many users in the list were created within the cutoff period.
*
* @param users
* @param period
*/
export function countNewAccounts(users: User[], period: PrivyLoginsPeriod): number {
const cutoffMs = getCutoffMs(period);
Expand Down
4 changes: 4 additions & 0 deletions lib/admins/privy/fetchPrivyLogins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export type FetchPrivyLoginsResult = {
totalPrivyUsers: number;
};

/**
*
* @param period
*/
Comment on lines +23 to +26
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove duplicate JSDoc block.

This empty JSDoc block duplicates the comprehensive documentation already present at lines 8-17 (which includes a proper description, @see link, @param, and @returns). The added block diminishes documentation quality.

🧹 Suggested fix: remove the redundant block
-/**
- *
- * `@param` period
- */
 export async function fetchPrivyLogins(period: PrivyLoginsPeriod): Promise<FetchPrivyLoginsResult> {
📝 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.

Suggested change
/**
*
* @param period
*/
export async function fetchPrivyLogins(period: PrivyLoginsPeriod): Promise<FetchPrivyLoginsResult> {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/admins/privy/fetchPrivyLogins.ts` around lines 23 - 26, Remove the
redundant empty JSDoc block that appears just above the fetchPrivyLogins
function; keep the original comprehensive JSDoc (the detailed block with
description, `@see`, `@param`, and `@returns`) and delete the duplicate empty block so
only the full documentation for fetchPrivyLogins remains.

export async function fetchPrivyLogins(period: PrivyLoginsPeriod): Promise<FetchPrivyLoginsResult> {
const isAll = period === "all";
const cutoffMs = getCutoffMs(period);
Expand Down
Loading
Loading