c6a3ee0e9a
* show model name in footer, drop pullfrog.com link add model slug to buildPullfrogFooter so every Pullfrog comment displays the active model (e.g. "Using `Big Pickle` (free)" or "Using `Claude Opus`"). remove the pullfrog.com link from all footers. Made-with: Cursor * reject <br/> tags in comment bodies, add prompt guidance add runtime validation in addFooter that throws if <br/> is followed by a non-blank line (breaks GitHub heading rendering). the agent sees the error and retries with clean markdown. also update Summarize mode prompt to explicitly forbid <br/> tags. Made-with: Cursor * fix <br/> guidance: move to event instructions, clarify blank line rule the formatting rule belongs in DEFAULT_PR_SUMMARY_INSTRUCTIONS (event instructions), not the Summarize mode prompt. clarify that <br/> must always be followed by a blank line before headings. Made-with: Cursor * generalize block-level HTML rule in summary instructions add a prominent top-level rule about requiring blank lines between ALL block-level HTML elements and markdown syntax, not just <br/>. Made-with: Cursor * move model to toolState instead of threading through params model is set once at startup and read everywhere — it belongs on toolState, not threaded as a separate param through 8 call sites. postCleanup runs without toolState so it just omits the model label. Made-with: Cursor * update models.dev snapshot (openai latest changed) Made-with: Cursor * add comment to models snapshot test explaining its purpose Made-with: Cursor
79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
import { modelAliases } from "../models.ts";
|
||
|
||
export const PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
|
||
|
||
const FROG_LOGO = `<a href="https://pullfrog.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pullfrog.com/logos/frog-white-full-18px.png"><img src="https://pullfrog.com/logos/frog-green-full-18px.png" width="9px" height="9px" style="vertical-align: middle; " alt="Pullfrog"></picture></a>`;
|
||
|
||
export interface WorkflowRunFooterInfo {
|
||
owner: string;
|
||
repo: string;
|
||
runId: number;
|
||
/** optional job ID - if provided, will append /job/{jobId} to the workflow run URL */
|
||
jobId?: string | undefined;
|
||
}
|
||
|
||
export interface BuildPullfrogFooterParams {
|
||
/** add "Triggered by Pullfrog" link */
|
||
triggeredBy?: boolean;
|
||
/** add "View workflow run" link */
|
||
workflowRun?: WorkflowRunFooterInfo | undefined;
|
||
/** alternative: just pass a pre-built URL directly (for shortlinks etc.) */
|
||
workflowRunUrl?: string | undefined;
|
||
/** arbitrary custom parts (e.g., action links) */
|
||
customParts?: string[] | undefined;
|
||
/** model slug from payload (e.g., "anthropic/claude-opus"). shown in footer as "Using `Model Name`" */
|
||
model?: string | undefined;
|
||
}
|
||
|
||
function formatModelLabel(slug: string): string {
|
||
const alias = modelAliases.find((a) => a.slug === slug);
|
||
if (!alias) return `\`${slug}\``;
|
||
return alias.isFree ? `\`${alias.displayName}\` (free)` : `\`${alias.displayName}\``;
|
||
}
|
||
|
||
/**
|
||
* build a pullfrog footer with configurable parts
|
||
* always includes: frog logo at start and X link at end
|
||
* order: action links (customParts) > workflow run > model > attribution > reference links
|
||
*/
|
||
export function buildPullfrogFooter(params: BuildPullfrogFooterParams): string {
|
||
const parts: string[] = [];
|
||
|
||
if (params.customParts) {
|
||
parts.push(...params.customParts);
|
||
}
|
||
|
||
if (params.workflowRunUrl) {
|
||
parts.push(`[View workflow run](${params.workflowRunUrl})`);
|
||
} else if (params.workflowRun) {
|
||
const baseUrl = `https://github.com/${params.workflowRun.owner}/${params.workflowRun.repo}/actions/runs/${params.workflowRun.runId}`;
|
||
const url = params.workflowRun.jobId ? `${baseUrl}/job/${params.workflowRun.jobId}` : baseUrl;
|
||
parts.push(`[View workflow run](${url})`);
|
||
}
|
||
|
||
if (params.triggeredBy) {
|
||
parts.push("Triggered by [Pullfrog](https://pullfrog.com)");
|
||
}
|
||
|
||
if (params.model) {
|
||
parts.push(`Using ${formatModelLabel(params.model)}`);
|
||
}
|
||
|
||
const allParts = [...parts, "[𝕏](https://x.com/pullfrogai)"];
|
||
|
||
return `
|
||
${PULLFROG_DIVIDER}
|
||
<sup>${FROG_LOGO} | ${allParts.join(" | ")}</sup>`;
|
||
}
|
||
|
||
/**
|
||
* strip any existing pullfrog footer from a comment body
|
||
*/
|
||
export function stripExistingFooter(body: string): string {
|
||
const dividerIndex = body.indexOf(PULLFROG_DIVIDER);
|
||
if (dividerIndex === -1) {
|
||
return body;
|
||
}
|
||
return body.substring(0, dividerIndex).trimEnd();
|
||
}
|