overhaul git setup

This commit is contained in:
Colin McDonnell
2025-12-16 18:00:22 -08:00
parent f6ac916e22
commit 1bff21f7fb
19 changed files with 514 additions and 195 deletions
+2 -2
View File
@@ -14,11 +14,11 @@ export const claude = agent({
executablePath: "cli.js",
});
},
run: async ({ payload, mcpServers, apiKey, cliPath, prepResults }) => {
run: async ({ payload, mcpServers, apiKey, cliPath, prepResults, repo }) => {
// Ensure API key is NOT in process.env - only pass via SDK's env option
delete process.env.ANTHROPIC_API_KEY;
const prompt = addInstructions({ payload, prepResults });
const prompt = addInstructions({ payload, prepResults, repo });
console.log(prompt);
// configure sandbox mode if enabled
+2 -2
View File
@@ -20,7 +20,7 @@ export const codex = agent({
executablePath: "bin/codex.js",
});
},
run: async ({ payload, mcpServers, apiKey, cliPath, prepResults }) => {
run: async ({ payload, mcpServers, apiKey, cliPath, prepResults, repo }) => {
// create config directory for codex before setting HOME
const tempHome = process.env.PULLFROG_TEMP_DIR!;
const configDir = join(tempHome, ".config", "codex");
@@ -61,7 +61,7 @@ export const codex = agent({
);
try {
const streamedTurn = await thread.runStreamed(addInstructions({ payload, prepResults }));
const streamedTurn = await thread.runStreamed(addInstructions({ payload, prepResults, repo }));
let finalOutput = "";
for await (const event of streamedTurn.events) {
+2 -2
View File
@@ -91,7 +91,7 @@ export const cursor = agent({
executableName: "cursor-agent",
});
},
run: async ({ payload, apiKey, cliPath, mcpServers, prepResults }) => {
run: async ({ payload, apiKey, cliPath, mcpServers, prepResults, repo }) => {
configureCursorMcpServers({ mcpServers, cliPath });
configureCursorSandbox({ sandbox: payload.sandbox ?? false });
@@ -166,7 +166,7 @@ export const cursor = agent({
};
try {
const fullPrompt = addInstructions({ payload, prepResults });
const fullPrompt = addInstructions({ payload, prepResults, repo });
// configure sandbox mode if enabled
// in sandbox mode: remove --force flag and rely on cli-config.json sandbox settings
+2 -2
View File
@@ -154,14 +154,14 @@ export const gemini = agent({
...(githubInstallationToken && { githubInstallationToken }),
});
},
run: async ({ payload, apiKey, mcpServers, cliPath, prepResults }) => {
run: async ({ payload, apiKey, mcpServers, cliPath, prepResults, repo }) => {
configureGeminiMcpServers({ mcpServers, cliPath });
if (!apiKey) {
throw new Error("google_api_key or gemini_api_key is required for gemini agent");
}
const sessionPrompt = addInstructions({ payload, prepResults });
const sessionPrompt = addInstructions({ payload, prepResults, repo });
log.info(`Starting Gemini CLI with prompt: ${payload.prompt.substring(0, 100)}...`);
// configure sandbox mode if enabled
+73 -12
View File
@@ -1,3 +1,4 @@
import { execSync } from "node:child_process";
import { encode as toonEncode } from "@toon-format/toon";
import type { Payload } from "../external.ts";
import { ghPullfrogMcpName } from "../external.ts";
@@ -62,19 +63,74 @@ function formatPrepResults(results: PrepResult[]): string {
return "";
}
return `************* ENVIRONMENT SETUP *************
return lines.join("\n");
}
${lines.join("\n")}
interface RepoInfo {
owner: string;
name: string;
defaultBranch: string;
}
`;
interface BuildRuntimeContextParams {
repo: RepoInfo;
prepResults: PrepResult[];
}
/**
* Build runtime context string with git status, repo data, and GitHub Actions variables
*/
function buildRuntimeContext({ repo, prepResults }: BuildRuntimeContextParams): string {
const lines: string[] = [];
// working directory
lines.push(`working_directory: ${process.cwd()}`);
// git status (try to get it, but don't fail if git isn't available)
try {
const gitStatus = execSync("git status --short", { encoding: "utf-8", stdio: "pipe" }).trim();
lines.push(`git_status: ${gitStatus || "(clean)"}`);
} catch {
// git not available or not in a repo
}
// repo data
lines.push(`repo: ${repo.owner}/${repo.name}`);
lines.push(`default_branch: ${repo.defaultBranch}`);
// GitHub Actions variables (when running in CI)
const ghVars: Record<string, string | undefined> = {
github_event_name: process.env.GITHUB_EVENT_NAME,
github_ref: process.env.GITHUB_REF,
github_sha: process.env.GITHUB_SHA?.slice(0, 7),
github_actor: process.env.GITHUB_ACTOR,
github_run_id: process.env.GITHUB_RUN_ID,
github_workflow: process.env.GITHUB_WORKFLOW,
};
for (const [key, value] of Object.entries(ghVars)) {
if (value) {
lines.push(`${key}: ${value}`);
}
}
// environment setup (dependency installation results)
const envSetup = formatPrepResults(prepResults);
if (envSetup) {
lines.push("");
lines.push("environment_setup:");
lines.push(envSetup);
}
return lines.join("\n");
}
interface AddInstructionsParams {
payload: Payload;
prepResults: PrepResult[];
repo: RepoInfo;
}
export const addInstructions = ({ payload, prepResults }: AddInstructionsParams) => {
export const addInstructions = ({ payload, prepResults, repo }: AddInstructionsParams) => {
let encodedEvent = "";
const eventKeys = Object.keys(payload.event);
@@ -86,7 +142,7 @@ export const addInstructions = ({ payload, prepResults }: AddInstructionsParams)
encodedEvent = toonEncode(payload.event);
}
const envSetup = formatPrepResults(prepResults);
const runtimeContext = buildRuntimeContext({ repo, prepResults });
const dependenciesPreinstalled = prepResults.every((r) => r.dependenciesInstalled) || undefined;
return `
@@ -163,14 +219,21 @@ Tool names may be formatted as \`(server name)/(tool name)\`, for example: \`${g
**Git operations**: All git operations must use ${ghPullfrogMcpName} MCP tools to ensure proper authentication and commit attribution. Do NOT use git commands directly (e.g., \`git commit\`, \`git push\`, \`git checkout\`, \`git branch\`) - these will use incorrect credentials and attribute commits to the wrong author.
**Available git MCP tools**:
- \`${ghPullfrogMcpName}/checkout_pr\` - Checkout an existing PR branch locally (handles fork PRs automatically)
- \`${ghPullfrogMcpName}/create_branch\` - Create a new branch from a base branch
- \`${ghPullfrogMcpName}/commit_files\` - Stage and commit files with proper authentication
- \`${ghPullfrogMcpName}/push_branch\` - Push a branch to the remote repository
- \`${ghPullfrogMcpName}/push_branch\` - Push a branch to the remote (automatically uses correct remote for fork PRs)
- \`${ghPullfrogMcpName}/create_pull_request\` - Create a PR from the current branch
**Workflow for making code changes**:
1. Use file operations to create/modify files
2. Use \`${ghPullfrogMcpName}/create_branch\` to create a new branch
**Workflow for working on an existing PR**:
1. Use \`${ghPullfrogMcpName}/checkout_pr\` to checkout the PR branch
2. Make your changes using file operations
3. Use \`${ghPullfrogMcpName}/commit_files\` to commit your changes
4. Use \`${ghPullfrogMcpName}/push_branch\` to push (automatically pushes to fork for fork PRs)
**Workflow for creating new changes**:
1. Use \`${ghPullfrogMcpName}/create_branch\` to create a new branch
2. Make your changes using file operations
3. Use \`${ghPullfrogMcpName}/commit_files\` to commit your changes
4. Use \`${ghPullfrogMcpName}/push_branch\` to push the branch
5. Use \`${ghPullfrogMcpName}/create_pull_request\` to create a PR
@@ -221,7 +284,5 @@ ${encodedEvent}`
************* RUNTIME CONTEXT *************
working_directory: ${process.cwd()}
${envSetup}`;
${runtimeContext}`;
};
+2 -2
View File
@@ -304,7 +304,7 @@ export const opencode = agent({
installDependencies: true,
});
},
run: async ({ payload, apiKey: _apiKey, apiKeys, mcpServers, cliPath, prepResults }) => {
run: async ({ payload, apiKey: _apiKey, apiKeys, mcpServers, cliPath, prepResults, repo }) => {
// 1. configure home/config directory
const tempHome = process.env.PULLFROG_TEMP_DIR!;
const configDir = join(tempHome, ".config", "opencode");
@@ -313,7 +313,7 @@ export const opencode = agent({
configureOpenCodeMcpServers({ mcpServers });
configureOpenCodeSandbox({ sandbox: payload.sandbox ?? false });
const prompt = addInstructions({ payload, prepResults });
const prompt = addInstructions({ payload, prepResults, repo });
const args = ["run", "--format", "json", prompt];
if (payload.sandbox) {
+10
View File
@@ -21,6 +21,15 @@ export interface AgentResult {
metadata?: Record<string, unknown>;
}
/**
* Repo info for agent context
*/
export interface RepoInfo {
owner: string;
name: string;
defaultBranch: string;
}
/**
* Configuration for agent creation
*/
@@ -31,6 +40,7 @@ export interface AgentConfig {
mcpServers: Record<string, McpHttpServerConfig>;
cliPath: string;
prepResults: PrepResult[];
repo: RepoInfo;
}
/**