import { createServerFn } from "@tanstack/react-start"; import { z } from "zod"; import { requireViewer, viewerMiddleware } from "./middleware"; import { limitHeavy } from "~/server/limits"; import { assertVerifiedForWrites } from "~/server/verified-writes"; import { requireRepoAccess } from "~/server/repos"; import { compareBranches } from "~/server/git/compare"; import { badRequest, forbidden } from "~/server/errors"; import { loadRepoSettings } from "~/server/mergefix/store"; import { suggestPullDescription as suggest } from "~/server/pull-describe/service"; import { repoRef } from "~/lib/validation"; /** Billed to the viewer (their plan or their own key), never the repository owner: any reader can open a pull request. */ export const suggestPullDescription = createServerFn({ method: "POST" }) .middleware([viewerMiddleware]) .validator(repoRef.extend({ base: z.string().min(1), head: z.string().min(1) })) .handler(async ({ data, context }) => { const viewer = requireViewer(context.viewer); assertVerifiedForWrites(viewer); await limitHeavy(viewer); const { repo } = await requireRepoAccess(data.owner, data.repo, viewer, "read"); // Private code only goes to a model when the repository opted in (the same switch as merge fixes). if (repo.visibility !== "public" && !(await loadRepoSettings(repo.id)).allowPrivate) throw forbidden("AI features are off for this private repository"); const compared = await compareBranches(repo, data.base, data.head, viewer); const headRepo = compared.headRepo; if ( headRepo.id !== repo.id && headRepo.visibility !== "public" && !(await loadRepoSettings(headRepo.id)).allowPrivate ) throw forbidden("AI features are off for the private head repository"); if (compared.comparison.commits.length === 0) throw badRequest("There are no commits to describe"); return suggest( { accountId: viewer.id, repoId: repo.id }, { base: compared.base.name, head: compared.head.name, commits: compared.comparison.commits, diff: compared.diff }, ); });