Skip to content

refactor(agent): extract hasTTY env checks to NonInteractiveDetector#658

Open
mvanhorn wants to merge 1 commit intoentireio:mainfrom
mvanhorn:refactor/hasTTY-agent-interface
Open

refactor(agent): extract hasTTY env checks to NonInteractiveDetector#658
mvanhorn wants to merge 1 commit intoentireio:mainfrom
mvanhorn:refactor/hasTTY-agent-interface

Conversation

@mvanhorn
Copy link
Contributor

@mvanhorn mvanhorn commented Mar 8, 2026

Summary

Closes #601

Replaces the hardcoded environment variable checks in hasTTY() with a new optional NonInteractiveDetector interface that agents can implement. This makes the non-interactive detection extensible - new agents can declare their env vars without touching the strategy package.

Before

// manual_commit_hooks.go - hardcoded checks
if os.Getenv("GEMINI_CLI") != "" { return false }
if os.Getenv("COPILOT_CLI") != "" { return false }
if os.Getenv("GIT_TERMINAL_PROMPT") == "0" { return false }

After

// agent.go - optional interface
type NonInteractiveDetector interface {
    Agent
    NonInteractiveEnvVar() (name string, value string)
}

// manual_commit_hooks.go - single call
if agent.IsNonInteractiveEnv() { return false }

The (name, value) tuple return handles both patterns:

  • "Any non-empty value" (Gemini, Copilot) - return ("GEMINI_CLI", "")
  • "Exact value match" (Factory AI Droid) - return ("GIT_TERMINAL_PROMPT", "0")

Changes

  • agent/agent.go - Added NonInteractiveDetector interface
  • agent/registry.go - Added IsNonInteractiveEnv() helper that iterates registered agents
  • agent/registry_test.go - 5 subtests covering empty registry, unset var, any-value match, exact-value match, and exact-value mismatch
  • agent/geminicli/gemini.go - Implements NonInteractiveEnvVar() -> ("GEMINI_CLI", "")
  • agent/copilotcli/copilotcli.go - Implements NonInteractiveEnvVar() -> ("COPILOT_CLI", "")
  • agent/factoryaidroid/factoryaidroid.go - Implements NonInteractiveEnvVar() -> ("GIT_TERMINAL_PROMPT", "0")
  • strategy/manual_commit_hooks.go - Replaced 3 hardcoded checks with single agent.IsNonInteractiveEnv() call

Testing

  • 5 new unit tests for IsNonInteractiveEnv() covering all edge cases
  • Uses mock agent struct with test-only registration/cleanup
  • All existing tests continue to pass

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

…r interface

Replace hardcoded GEMINI_CLI, COPILOT_CLI, and GIT_TERMINAL_PROMPT
checks in hasTTY() with an optional agent interface. Agents whose hook
subprocesses inherit the user's TTY but can't respond to prompts now
implement NonInteractiveDetector with their env var, so adding a new
agent no longer requires changes to the strategy layer.

Closes entireio#601

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Refactor hasTTY() to use optional agent interface for non-interactive subprocess detection

1 participant