feat(agent-api): POST /api/agent/cards/:cardId/comments
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a297fe5f15
commit
0e74dbdf14
1 changed files with 55 additions and 0 deletions
55
src/app/api/agent/cards/[cardId]/comments/route.ts
Normal file
55
src/app/api/agent/cards/[cardId]/comments/route.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import { getAdminPb } from "@/lib/pb/admin";
|
||||
import { requireAgentToken } from "@/lib/agent/auth";
|
||||
import { getOwnerUser } from "@/lib/agent/owner";
|
||||
import { jsonError, jsonOk } from "@/lib/http/json";
|
||||
import type { CardRecord } from "@/lib/pb/types";
|
||||
|
||||
/** Matches the comments collection's own `body` field limit. */
|
||||
const MAX_BODY_LENGTH = 20000;
|
||||
|
||||
/**
|
||||
* POST /api/agent/cards/:cardId/comments — post a drafted plan as a comment.
|
||||
*
|
||||
* The stored body is always prefixed before being written, so no caller can
|
||||
* accidentally or deliberately post something indistinguishable from the
|
||||
* owner's own words. This prefix is the one thing this whole feature exists
|
||||
* to guarantee — do not make it conditional or configurable.
|
||||
*/
|
||||
export async function POST(
|
||||
request: Request,
|
||||
context: { params: Promise<{ cardId: string }> }
|
||||
): Promise<Response> {
|
||||
const denied = requireAgentToken(request);
|
||||
if (denied) return denied;
|
||||
|
||||
const { cardId } = await context.params;
|
||||
|
||||
let json: unknown;
|
||||
try {
|
||||
json = await request.json();
|
||||
} catch {
|
||||
return jsonError("Invalid request body", 400);
|
||||
}
|
||||
|
||||
const body = (json as { body?: unknown } | null)?.body;
|
||||
if (typeof body !== "string" || !body.trim()) {
|
||||
return jsonError("A non-empty body is required", 400);
|
||||
}
|
||||
|
||||
const pb = await getAdminPb();
|
||||
const card = await pb.collection("cards").getOne<CardRecord>(cardId).catch(() => null);
|
||||
if (!card || card.archived) return jsonError("Card not found", 404);
|
||||
|
||||
const owner = await getOwnerUser();
|
||||
|
||||
const prefix = "🤖 Drafted by your agent:\n\n";
|
||||
const trimmed = body.trim().slice(0, MAX_BODY_LENGTH - prefix.length);
|
||||
|
||||
const comment = await pb.collection("comments").create({
|
||||
card: cardId,
|
||||
author: owner.id,
|
||||
body: `${prefix}${trimmed}`,
|
||||
});
|
||||
|
||||
return jsonOk({ id: comment.id }, 201);
|
||||
}
|
||||
Loading…
Reference in a new issue