-
Notifications
You must be signed in to change notification settings - Fork 4
agent: @U0AJM7X8FBR API - MPP • actual: using x402 for many endpoints • require #315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: test
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove duplicate/incorrect The 🧹 Suggested fix * `@param` request - The incoming verification request
- * `@param` params.params
* `@param` params - Route params containing the platform name📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| */ | ||||||||||||
| export async function GET( | ||||||||||||
|
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same issue: remove duplicate/incorrect The 🧹 Suggested fix * `@param` request - The incoming webhook request
- * `@param` params.params
* `@param` params - Route params containing the platform name📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| */ | ||||||||||||
| export async function POST( | ||||||||||||
|
|
||||||||||||
| 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); | ||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Payer address not validated after extraction.
🛡️ 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Destructuring before null check causes potential runtime error. Line 68 destructures 🐛 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| 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() }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,6 +20,10 @@ export type FetchPrivyLoginsResult = { | |||||||||||
| totalPrivyUsers: number; | ||||||||||||
| }; | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * | ||||||||||||
| * @param period | ||||||||||||
| */ | ||||||||||||
|
Comment on lines
+23
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove duplicate JSDoc block. This empty JSDoc block duplicates the comprehensive documentation already present at lines 8-17 (which includes a proper description, 🧹 Suggested fix: remove the redundant block-/**
- *
- * `@param` period
- */
export async function fetchPrivyLogins(period: PrivyLoginsPeriod): Promise<FetchPrivyLoginsResult> {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| export async function fetchPrivyLogins(period: PrivyLoginsPeriod): Promise<FetchPrivyLoginsResult> { | ||||||||||||
| const isAll = period === "all"; | ||||||||||||
| const cutoffMs = getCutoffMs(period); | ||||||||||||
|
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect and redundant
@paramentry.Line 26 adds
@param params.paramswhich is malformed—there's noparams.paramsin the function signature. The existing line 27 already documents theparamsparameter 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
🤖 Prompt for AI Agents