1d59fd3d21
* flatten lifecycle hooks into RepoSettings string fields replace the separate LifecycleHook model with setupScript and postCheckoutScript string fields directly on RepoSettings. move the UI into the Agent settings section alongside environment variables and custom instructions. delete the standalone lifecycle-hooks API route, component, and schema since the existing settings PATCH endpoint handles the new fields automatically. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: pass env to lifecycle hook spawn so scripts can use package managers Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Colin McDonnell <colinmcd94@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
103 lines
2.4 KiB
TypeScript
103 lines
2.4 KiB
TypeScript
import type { AgentName, BashPermission, PushPermission, 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;
|
|
modes: Mode[];
|
|
setupScript: string | null;
|
|
postCheckoutScript: string | null;
|
|
repoInstructions: string;
|
|
web: ToolPermission;
|
|
search: ToolPermission;
|
|
push: PushPermission;
|
|
bash: BashPermission;
|
|
}
|
|
|
|
export interface RunContext {
|
|
settings: RepoSettings;
|
|
apiToken: string;
|
|
}
|
|
|
|
const defaultSettings: RepoSettings = {
|
|
defaultAgent: null,
|
|
modes: [],
|
|
setupScript: null,
|
|
postCheckoutScript: null,
|
|
repoInstructions: "",
|
|
web: "enabled",
|
|
search: "enabled",
|
|
push: "restricted",
|
|
bash: "restricted",
|
|
};
|
|
|
|
const defaultRunContext: RunContext = {
|
|
settings: defaultSettings,
|
|
apiToken: "",
|
|
};
|
|
|
|
/**
|
|
* fetch run context from Pullfrog API
|
|
* returns settings + API token for subsequent calls
|
|
* returns defaults if fetch fails
|
|
*/
|
|
export async function fetchRunContext(params: {
|
|
token: string;
|
|
repoContext: RepoContext;
|
|
}): Promise<RunContext> {
|
|
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
|
const timeoutMs = 30000;
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
|
|
try {
|
|
const response = await fetch(
|
|
`${apiUrl}/api/repo/${params.repoContext.owner}/${params.repoContext.name}/run-context`,
|
|
{
|
|
method: "GET",
|
|
headers: {
|
|
Authorization: `Bearer ${params.token}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
signal: controller.signal,
|
|
}
|
|
);
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response.ok) {
|
|
return defaultRunContext;
|
|
}
|
|
|
|
const data = (await response.json()) as {
|
|
settings: RepoSettings | null;
|
|
apiToken: string;
|
|
} | null;
|
|
|
|
if (data === null) {
|
|
return defaultRunContext;
|
|
}
|
|
|
|
return {
|
|
settings: {
|
|
...defaultSettings,
|
|
...data.settings,
|
|
// ensure arrays are never undefined (API may omit new fields for existing repos)
|
|
modes: data.settings?.modes ?? [],
|
|
setupScript: data.settings?.setupScript ?? null,
|
|
postCheckoutScript: data.settings?.postCheckoutScript ?? null,
|
|
},
|
|
apiToken: data.apiToken,
|
|
};
|
|
} catch {
|
|
clearTimeout(timeoutId);
|
|
return defaultRunContext;
|
|
}
|
|
}
|