UNPKG

@nanocollective/nanocoder

Version:

A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter

147 lines 6.35 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * Git Log Tool * * View commit history with various filters. */ import { Box, Text } from 'ink'; import { useTheme } from '../../hooks/useTheme.js'; import { jsonSchema, tool } from '../../types/core.js'; import { getCommits, getCurrentBranch } from './utils.js'; // ============================================================================ // Execution // ============================================================================ const executeGitLog = async (args) => { try { const count = Math.min(args.count || 10, 50); // Cap at 50 const branch = args.branch || (await getCurrentBranch()); const commits = await getCommits({ count, file: args.file, author: args.author, since: args.since, grep: args.grep, }); if (commits.length === 0) { const filters = []; if (args.author) filters.push(`author: ${args.author}`); if (args.since) filters.push(`since: ${args.since}`); if (args.grep) filters.push(`grep: ${args.grep}`); if (args.file) filters.push(`file: ${args.file}`); if (filters.length > 0) { return `No commits found matching filters: ${filters.join(', ')}`; } return 'No commits found.'; } const lines = []; lines.push(`Showing ${commits.length} commit(s) on ${branch}:`); lines.push(''); for (const commit of commits) { lines.push(`${commit.shortHash} ${commit.subject} (${commit.relativeDate})`); lines.push(` Author: ${commit.author} <${commit.email}>`); } return lines.join('\n'); } catch (error) { return `Error: ${error instanceof Error ? error.message : 'Unknown error'}`; } }; // ============================================================================ // Tool Definition // ============================================================================ const gitLogCoreTool = tool({ description: 'View git commit history. Supports filtering by count, file, author, date, and commit message search.', inputSchema: jsonSchema({ type: 'object', properties: { count: { type: 'number', description: 'Number of commits to show (default: 10, max: 50)', }, file: { type: 'string', description: 'Show history for a specific file', }, author: { type: 'string', description: 'Filter by author name or email', }, since: { type: 'string', description: 'Show commits after date (e.g., "2024-01-01", "1 week ago")', }, grep: { type: 'string', description: 'Search commit messages for a pattern', }, branch: { type: 'string', description: 'Show commits on a specific branch (default: current)', }, }, required: [], }), // AUTO - read-only operation, never needs approval needsApproval: () => false, execute: async (args, _options) => { return await executeGitLog(args); }, }); // ============================================================================ // Formatter // ============================================================================ function GitLogFormatter({ args, result, }) { const { colors } = useTheme(); // Parse result for display let commitCount = 0; let branch = ''; let dateRange = ''; if (result) { const countMatch = result.match(/Showing (\d+) commit/); if (countMatch) commitCount = parseInt(countMatch[1], 10); const branchMatch = result.match(/on (.+):/); if (branchMatch) branch = branchMatch[1]; // Extract date range from commits (looking for relative dates like "2 hours ago") const dateMatches = result.match(/\((\d+\s+\w+\s+ago|today|yesterday)\)/gi); if (dateMatches && dateMatches.length > 0) { const first = dateMatches[0].replace(/[()]/g, ''); const last = dateMatches[dateMatches.length - 1].replace(/[()]/g, ''); if (first !== last) { dateRange = `${last} → ${first}`; } else { dateRange = first; } } } // Build filter description const filters = []; if (args.author) filters.push(`author: ${args.author}`); if (args.since) filters.push(`since: ${args.since}`); if (args.grep) filters.push(`grep: "${args.grep}"`); if (args.file) filters.push(`file: ${args.file}`); return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: colors.tool, children: "\u2692 git_log" }), branch && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Branch: " }), _jsx(Text, { color: colors.primary, children: branch })] })), commitCount > 0 && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Showing: " }), _jsxs(Text, { color: colors.text, children: [commitCount, " commits"] })] })), dateRange && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Range: " }), _jsx(Text, { color: colors.text, children: dateRange })] })), filters.length > 0 && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Filters: " }), _jsx(Text, { color: colors.text, children: filters.join(', ') })] })), commitCount === 0 && result && (_jsx(Box, { children: _jsx(Text, { color: colors.warning, children: "No commits found" }) }))] })); } const formatter = (args, result) => { return _jsx(GitLogFormatter, { args: args, result: result }); }; // ============================================================================ // Export // ============================================================================ export const gitLogTool = { name: 'git_log', tool: gitLogCoreTool, formatter, readOnly: true, }; //# sourceMappingURL=git-log.js.map