Commit 1f9e459
Changed files (4)
lib
lib/elelem/git_context.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Elelem
+ class GitContext
+ MAX_DIFF_LINES = 100
+
+ def initialize(shell = Elelem.shell)
+ @shell = shell
+ end
+
+ def to_s
+ return "" unless git_repo?
+
+ parts = []
+ parts << "Branch: #{branch}" if branch
+ parts << status_section if status.any?
+ parts << diff_section if staged_diff.any? || unstaged_diff.any?
+ parts << recent_commits_section if recent_commits.any?
+ parts.join("\n\n")
+ end
+
+ private
+
+ def git_repo?
+ @shell.execute("git", args: ["rev-parse", "--git-dir"])["exit_status"].zero?
+ end
+
+ def branch
+ @branch ||= @shell.execute("git", args: ["branch", "--show-current"])["stdout"].strip
+ end
+
+ def status
+ @status ||= @shell.execute("git", args: ["status", "--porcelain"])["stdout"].lines.map(&:strip)
+ end
+
+ def staged_diff
+ @staged_diff ||= @shell.execute("git", args: ["diff", "--cached", "--stat"])["stdout"].lines
+ end
+
+ def unstaged_diff
+ @unstaged_diff ||= @shell.execute("git", args: ["diff", "--stat"])["stdout"].lines
+ end
+
+ def recent_commits
+ @recent_commits ||= @shell.execute("git", args: ["log", "--oneline", "-5"])["stdout"].lines.map(&:strip)
+ end
+
+ def status_section
+ modified = status.select { |l| l.start_with?(" M", "M ") }.map { |l| l[3..] }
+ added = status.select { |l| l.start_with?("A ", "??") }.map { |l| l[3..] }
+ deleted = status.select { |l| l.start_with?(" D", "D ") }.map { |l| l[3..] }
+
+ lines = []
+ lines << "Modified: #{modified.join(', ')}" if modified.any?
+ lines << "Added: #{added.join(', ')}" if added.any?
+ lines << "Deleted: #{deleted.join(', ')}" if deleted.any?
+ lines.any? ? "Working tree:\n#{lines.join("\n")}" : nil
+ end
+
+ def diff_section
+ lines = []
+ lines << "Staged:\n#{truncate(staged_diff)}" if staged_diff.any?
+ lines << "Unstaged:\n#{truncate(unstaged_diff)}" if unstaged_diff.any?
+ lines.join("\n\n")
+ end
+
+ def recent_commits_section
+ "Recent commits:\n#{recent_commits.join("\n")}"
+ end
+
+ def truncate(lines)
+ if lines.size > MAX_DIFF_LINES
+ lines.first(MAX_DIFF_LINES).join + "\n... (#{lines.size - MAX_DIFF_LINES} more lines)"
+ else
+ lines.join
+ end
+ end
+ end
+end
lib/elelem/system_prompt.erb
@@ -10,3 +10,7 @@ You are a trusted terminal agent. You act on behalf of the user - executing task
## System
<%= `uname -s`.strip %> · <%= ENV['PWD'] %>
+
+## Git State
+
+<%= Elelem::GitContext.new.to_s %>
lib/elelem.rb
@@ -17,6 +17,7 @@ require "timeout"
require_relative "elelem/agent"
require_relative "elelem/application"
require_relative "elelem/conversation"
+require_relative "elelem/git_context"
require_relative "elelem/terminal"
require_relative "elelem/tool"
require_relative "elelem/toolbox"
elelem.gemspec
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
"lib/elelem/agent.rb",
"lib/elelem/application.rb",
"lib/elelem/conversation.rb",
+ "lib/elelem/git_context.rb",
"lib/elelem/system_prompt.erb",
"lib/elelem/terminal.rb",
"lib/elelem/tool.rb",