UNPKG

hataraku

Version:

An autonomous coding agent for building AI-powered development tools. The name "Hataraku" (働く) means "to work" in Japanese.

126 lines 4.75 kB
import { exec } from "child_process"; import { promisify } from "util"; import { truncateOutput } from "../core/misc/extract-text"; const execAsync = promisify(exec); const GIT_OUTPUT_LINE_LIMIT = 500; async function checkGitRepo(cwd) { try { await execAsync('git rev-parse --git-dir', { cwd }); return true; } catch (error) { return false; } } async function checkGitInstalled() { try { await execAsync('git --version'); return true; } catch (error) { return false; } } export async function searchCommits(query, cwd) { try { const isInstalled = await checkGitInstalled(); if (!isInstalled) { console.error("Git is not installed"); return []; } const isRepo = await checkGitRepo(cwd); if (!isRepo) { console.error("Not a git repository"); return []; } // Search commits by hash or message, limiting to 10 results const { stdout } = await execAsync(`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` + `--grep="${query}" --regexp-ignore-case`, { cwd }); let output = stdout; if (!output.trim() && /^[a-f0-9]+$/i.test(query)) { // If no results from grep search and query looks like a hash, try searching by hash const { stdout: hashStdout } = await execAsync(`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` + `--author-date-order ${query}`, { cwd }).catch(() => ({ stdout: "" })); if (!hashStdout.trim()) { return []; } output = hashStdout; } const commits = []; const lines = output.trim().split("\n").filter(line => line !== "--"); for (let i = 0; i < lines.length; i += 5) { commits.push({ hash: lines[i], shortHash: lines[i + 1], subject: lines[i + 2], author: lines[i + 3], date: lines[i + 4] }); } return commits; } catch (error) { console.error("Error searching commits:", error); return []; } } export async function getCommitInfo(hash, cwd) { try { const isInstalled = await checkGitInstalled(); if (!isInstalled) { return "Git is not installed"; } const isRepo = await checkGitRepo(cwd); if (!isRepo) { return "Not a git repository"; } // Get commit info, stats, and diff separately const { stdout: info } = await execAsync(`git show --format="%H%n%h%n%s%n%an%n%ad%n%b" --no-patch ${hash}`, { cwd }); const [fullHash, shortHash, subject, author, date, body] = info.trim().split('\n'); const { stdout: stats } = await execAsync(`git show --stat --format="" ${hash}`, { cwd }); const { stdout: diff } = await execAsync(`git show --format="" ${hash}`, { cwd }); const summary = [ `Commit: ${shortHash} (${fullHash})`, `Author: ${author}`, `Date: ${date}`, `\nMessage: ${subject}`, body ? `\nDescription:\n${body}` : '', '\nFiles Changed:', stats.trim(), '\nFull Changes:' ].join('\n'); const output = summary + '\n\n' + diff.trim(); return truncateOutput(output, GIT_OUTPUT_LINE_LIMIT); } catch (error) { console.error("Error getting commit info:", error); return `Failed to get commit info: ${error instanceof Error ? error.message : String(error)}`; } } export async function getWorkingState(cwd) { try { const isInstalled = await checkGitInstalled(); if (!isInstalled) { return "Git is not installed"; } const isRepo = await checkGitRepo(cwd); if (!isRepo) { return "Not a git repository"; } // Get status of working directory const { stdout: status } = await execAsync('git status --short', { cwd }); if (!status.trim()) { return "No changes in working directory"; } // Get all changes (both staged and unstaged) compared to HEAD const { stdout: diff } = await execAsync('git diff HEAD', { cwd }); const lineLimit = GIT_OUTPUT_LINE_LIMIT; const output = `Working directory changes:\n\n${status}\n\n${diff}`.trim(); return truncateOutput(output, lineLimit); } catch (error) { console.error("Error getting working state:", error); return `Failed to get working state: ${error instanceof Error ? error.message : String(error)}`; } } //# sourceMappingURL=git.js.map