import { defineAction } from "@agent-native/core/action"; import { eq, and } from "drizzle-orm"; import { z } from "zod"; import { db, schema } from "../server/db/index.js"; import { hydrateQuotes } from "../server/lib/quotes.js"; import { withActionSpan } from "../server/otel.js"; export default defineAction({ description: "Submit a new poem quote. Finds the poem by author + title (case-insensitive) or creates it if it doesn't exist yet, then adds the quote under it, marked as user-submitted.", schema: z.object({ text: z.string().min(1).describe("The quote text (an excerpt from the poem)"), author: z.string().min(1).describe("The poet's name"), poemTitle: z.string().min(1).describe("Title of the poem this quote is from"), source: z.string().optional().describe("Collection/book the poem was published in"), year: z.coerce.number().int().optional().describe("Year the poem was written or published"), tags: z .array(z.string()) .optional() .describe("Theme tags for the quote, e.g. [\"hope\", \"nature\"]"), }), run: async (args) => { return withActionSpan( "create-quote", { author: args.author, poemTitle: args.poemTitle }, async () => { const existing = await db() .select() .from(schema.poems) .where( and( eq(schema.poems.author, args.author), eq(schema.poems.title, args.poemTitle), ), ) .limit(1); let poem = existing[0]; if (!poem) { const inserted = await db() .insert(schema.poems) .values({ author: args.author, title: args.poemTitle, source: args.source ?? null, year: args.year ?? null, }) .returning(); poem = inserted[0]; } const insertedQuote = await db() .insert(schema.quotes) .values({ poem_id: poem.id, text: args.text, tags_json: JSON.stringify(args.tags ?? []), is_user_submitted: true, }) .returning(); const [hydrated] = await hydrateQuotes([{ quote: insertedQuote[0], poem }]); return hydrated; }, ); }, });