import type { AgentName, BashPermission, ToolPermission } from "../external.ts"; import type { RepoContext } from "./github.ts"; export interface Mode { id: string; name: string; description: string; prompt: string; } export interface RepoSettings { defaultAgent: AgentName | null; web: ToolPermission; search: ToolPermission; write: ToolPermission; bash: BashPermission; modes: Mode[]; } export const DEFAULT_REPO_SETTINGS: RepoSettings = { defaultAgent: null, web: "enabled", search: "enabled", write: "enabled", bash: "restricted", modes: [], }; export interface WorkflowRunInfo { progressCommentId: string | null; issueNumber: number | null; } /** * Fetch workflow run info from the Pullfrog API * Returns the pre-created progress comment ID if one exists */ export async function fetchWorkflowRunInfo(runId: string): Promise { const apiUrl = process.env.API_URL || "https://pullfrog.com"; // add timeout to prevent hanging (30 seconds) const timeoutMs = 30000; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeoutMs); try { const response = await fetch(`${apiUrl}/api/workflow-run/${runId}`, { method: "GET", headers: { "Content-Type": "application/json", }, signal: controller.signal, }); clearTimeout(timeoutId); if (!response.ok) { return { progressCommentId: null, issueNumber: null }; } const data = (await response.json()) as WorkflowRunInfo; return data; } catch { clearTimeout(timeoutId); return { progressCommentId: null, issueNumber: null }; } } /** * Fetch repository settings from the Pullfrog API * Returns defaults if repo doesn't exist or fetch fails */ export async function fetchRepoSettings({ token, repoContext, }: { token: string; repoContext: RepoContext; }): Promise { const settings = await getRepoSettings(token, repoContext); return settings; } /** * Fetch repository settings from the Pullfrog API with fallback to defaults * Returns agent, permissions, and workflows (excludes triggers) * Returns defaults if repo doesn't exist or fetch fails */ export async function getRepoSettings( token: string, repoContext: RepoContext ): Promise { const apiUrl = process.env.API_URL || "https://pullfrog.com"; // Add timeout to prevent hanging (30 seconds) const timeoutMs = 30000; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeoutMs); try { const response = await fetch( `${apiUrl}/api/repo/${repoContext.owner}/${repoContext.name}/settings`, { method: "GET", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, signal: controller.signal, } ); clearTimeout(timeoutId); if (!response.ok) { // If API returns 404 or other error, fall back to defaults return DEFAULT_REPO_SETTINGS; } const settings = (await response.json()) as RepoSettings | null; // If API returns null (repo doesn't exist), return defaults if (settings === null) { return DEFAULT_REPO_SETTINGS; } return settings; } catch { clearTimeout(timeoutId); // If fetch fails (network error, timeout, etc.), fall back to defaults return DEFAULT_REPO_SETTINGS; } }