import { env } from "cloudflare:workers";
import { HttpError, paymentRequired } from "../errors";
import { chatCompletion, chatModel } from "../mergefix/gateway";
import { ModelCallError } from "../mergefix/plan";
import { resolveAiEndpoint, resolveAiEndpointSummary } from "../ai/endpoint";
import { aiMeter } from "../metering/ai";
import { billingSettings, hardCap, periodUsage } from "../metering/quota";
import { randomId } from "../crypto";
import { describeMessages, mockSuggestion, parseSuggestion } from "./prompt";
import type { DescribeInput, PullSuggestion } from "./prompt";
import { planAllowsAi } from "~/lib/plans";
import { captureServerEvent } from "../analytics";
const MAX_OUTPUT_TOKENS = 700;
const FEATURE = "pr-describe";
export type AiAccess = {
allowed: boolean;
/** Platform-billed calls used and allowed this period; null for BYOK accounts or uncapped plans. */
usage: { used: number; limit: number | null } | null;
};
/** Whether `accountId` may use AI features: a plan with ai.calls, or its own key (free, never capped). */
export async function aiAccessFor(accountId: string, repoId: string | null = null): Promise<AiAccess> {
const [settings, byok] = await Promise.all([
billingSettings(accountId),
resolveAiEndpointSummary({ accountId, repoId }),
]);
if (byok) return { allowed: true, usage: null };
if (!planAllowsAi(settings.plan)) return { allowed: false, usage: null };
const period = await periodUsage(accountId, "ai.calls");
return { allowed: true, usage: { used: period.quantity, limit: hardCap(settings, "ai.calls") } };
}
export function aiPaymentRequired(accountId: string): HttpError {
return paymentRequired("AI suggestions are available on paid plans", {
meter: "ai.calls",
reason: "paid_feature",
accountId,
});