Files
shockbot/utils/api.ts
T
Colin McDonnell 7407b6cbc5 Fix timeout
2025-12-22 12:51:04 -08:00

132 lines
3.4 KiB
TypeScript

import type { AgentName } 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;
webAccessLevel: "full_access" | "limited";
webAccessAllowTrusted: boolean;
webAccessDomains: string;
modes: Mode[];
}
export const DEFAULT_REPO_SETTINGS: RepoSettings = {
defaultAgent: null,
webAccessLevel: "full_access",
webAccessAllowTrusted: false,
webAccessDomains: "",
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<WorkflowRunInfo> {
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<RepoSettings> {
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<RepoSettings> {
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;
}
}