feat: Add Cursor, Auggie, and Sourcegraph AMP agent presets (#247)
* feat: add Cursor Agent as compatible agent for Gas Town Add AgentCursor preset with ProcessNames field for multi-agent detection: - AgentCursor preset: cursor-agent -p -f (headless + force mode) - ProcessNames field on AgentPresetInfo for agent detection - IsAgentRunning(session, processNames) in tmux package - GetProcessNames(agentName) helper function Closes: ga-vwr 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: centralize agent preset list in config.go Replace hardcoded ["claude", "gemini", "codex"] arrays with calls to config.ListAgentPresets() to dynamically include all registered agents. This fixes cursor agent not appearing in `gt config agent list` and ensures new agent presets are automatically included everywhere. Also updated doc comments to include "cursor" in example lists. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add comprehensive agent client tests Add tests for agent detection and command generation: - TestIsAgentRunning: validates process name detection for all agents (claude/node, gemini, codex, cursor-agent) - TestIsAgentRunning_NonexistentSession: edge case handling - TestIsClaudeRunning: backwards compatibility wrapper - TestListAgentPresetsMatchesConstants: ensures ListAgentPresets() returns all AgentPreset constants - TestAgentCommandGeneration: validates full command line generation for all supported agents 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add Auggie agent, fix Cursor interactive mode Add Auggie CLI as supported agent: - Command: auggie - Args: --allow-indexing - Supports session resume via --resume flag Fix Cursor agent configuration: - Remove -p flag (requires prompt, breaks interactive mode) - Clear SessionIDEnv (cursor uses --resume with chatId directly) - Keep -f flag for force/YOLO mode Updated all test cases for both agents. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(agents): add Sourcegraph AMP as agent preset Add AgentAmp constant and builtinPresets entry for Sourcegraph AMP CLI. Configuration: - Command: amp - Args: --dangerously-allow-all --no-ide - ResumeStyle: subcommand (amp threads continue <threadId>) - ProcessNames: amp Closes: ga-guq 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: lint error in cleanBeadsRuntimeFiles Change function to not return error (was always nil). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: beads v0.46.0 compatibility and test fixes - Add custom types config (agent,role,rig,convoy,event) after bd init calls - Fix tmux_test.go to use variadic IsAgentRunning signature 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: update agent documentation for new presets - README.md: Update agent examples to show cursor/auggie, add built-in presets list - docs/reference.md: Add cursor, auggie, amp to built-in agents list - CHANGELOG.md: Add entry for new agent presets under [Unreleased] Addresses PR #247 review feedback. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,12 +21,18 @@ const (
|
||||
AgentGemini AgentPreset = "gemini"
|
||||
// AgentCodex is OpenAI Codex.
|
||||
AgentCodex AgentPreset = "codex"
|
||||
// AgentCursor is Cursor Agent.
|
||||
AgentCursor AgentPreset = "cursor"
|
||||
// AgentAuggie is Auggie CLI.
|
||||
AgentAuggie AgentPreset = "auggie"
|
||||
// AgentAmp is Sourcegraph AMP.
|
||||
AgentAmp AgentPreset = "amp"
|
||||
)
|
||||
|
||||
// AgentPresetInfo contains the configuration details for an agent preset.
|
||||
// This extends the basic RuntimeConfig with agent-specific metadata.
|
||||
type AgentPresetInfo struct {
|
||||
// Name is the preset identifier (e.g., "claude", "gemini", "codex").
|
||||
// Name is the preset identifier (e.g., "claude", "gemini", "codex", "cursor", "auggie", "amp").
|
||||
Name AgentPreset `json:"name"`
|
||||
|
||||
// Command is the CLI binary to invoke.
|
||||
@@ -35,6 +41,11 @@ type AgentPresetInfo struct {
|
||||
// Args are the default command-line arguments for autonomous mode.
|
||||
Args []string `json:"args"`
|
||||
|
||||
// ProcessNames are the process names to look for when detecting if the agent is running.
|
||||
// Used by tmux.IsAgentRunning to check pane_current_command.
|
||||
// E.g., ["node"] for Claude, ["cursor-agent"] for Cursor.
|
||||
ProcessNames []string `json:"process_names,omitempty"`
|
||||
|
||||
// SessionIDEnv is the environment variable for session ID.
|
||||
// Used for resuming sessions across restarts.
|
||||
SessionIDEnv string `json:"session_id_env,omitempty"`
|
||||
@@ -91,6 +102,7 @@ var builtinPresets = map[AgentPreset]*AgentPresetInfo{
|
||||
Name: AgentClaude,
|
||||
Command: "claude",
|
||||
Args: []string{"--dangerously-skip-permissions"},
|
||||
ProcessNames: []string{"node"}, // Claude runs as Node.js
|
||||
SessionIDEnv: "CLAUDE_SESSION_ID",
|
||||
ResumeFlag: "--resume",
|
||||
ResumeStyle: "flag",
|
||||
@@ -102,6 +114,7 @@ var builtinPresets = map[AgentPreset]*AgentPresetInfo{
|
||||
Name: AgentGemini,
|
||||
Command: "gemini",
|
||||
Args: []string{"--approval-mode", "yolo"},
|
||||
ProcessNames: []string{"gemini"}, // Gemini CLI binary
|
||||
SessionIDEnv: "GEMINI_SESSION_ID",
|
||||
ResumeFlag: "--resume",
|
||||
ResumeStyle: "flag",
|
||||
@@ -116,6 +129,7 @@ var builtinPresets = map[AgentPreset]*AgentPresetInfo{
|
||||
Name: AgentCodex,
|
||||
Command: "codex",
|
||||
Args: []string{"--yolo"},
|
||||
ProcessNames: []string{"codex"}, // Codex CLI binary
|
||||
SessionIDEnv: "", // Codex captures from JSONL output
|
||||
ResumeFlag: "resume",
|
||||
ResumeStyle: "subcommand",
|
||||
@@ -126,6 +140,43 @@ var builtinPresets = map[AgentPreset]*AgentPresetInfo{
|
||||
OutputFlag: "--json",
|
||||
},
|
||||
},
|
||||
AgentCursor: {
|
||||
Name: AgentCursor,
|
||||
Command: "cursor-agent",
|
||||
Args: []string{"-f"}, // Force mode (YOLO equivalent), -p requires prompt
|
||||
ProcessNames: []string{"cursor-agent"},
|
||||
SessionIDEnv: "", // Uses --resume with chatId directly
|
||||
ResumeFlag: "--resume",
|
||||
ResumeStyle: "flag",
|
||||
SupportsHooks: false, // TODO: verify hooks support
|
||||
SupportsForkSession: false,
|
||||
NonInteractive: &NonInteractiveConfig{
|
||||
PromptFlag: "-p",
|
||||
OutputFlag: "--output-format json",
|
||||
},
|
||||
},
|
||||
AgentAuggie: {
|
||||
Name: AgentAuggie,
|
||||
Command: "auggie",
|
||||
Args: []string{"--allow-indexing"},
|
||||
ProcessNames: []string{"auggie"},
|
||||
SessionIDEnv: "",
|
||||
ResumeFlag: "--resume",
|
||||
ResumeStyle: "flag",
|
||||
SupportsHooks: false,
|
||||
SupportsForkSession: false,
|
||||
},
|
||||
AgentAmp: {
|
||||
Name: AgentAmp,
|
||||
Command: "amp",
|
||||
Args: []string{"--dangerously-allow-all", "--no-ide"},
|
||||
ProcessNames: []string{"amp"},
|
||||
SessionIDEnv: "",
|
||||
ResumeFlag: "threads continue",
|
||||
ResumeStyle: "subcommand", // 'amp threads continue <threadId>'
|
||||
SupportsHooks: false,
|
||||
SupportsForkSession: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Registry state with proper synchronization.
|
||||
@@ -305,6 +356,18 @@ func GetSessionIDEnvVar(agentName string) string {
|
||||
return info.SessionIDEnv
|
||||
}
|
||||
|
||||
// GetProcessNames returns the process names used to detect if an agent is running.
|
||||
// Used by tmux.IsAgentRunning to check pane_current_command.
|
||||
// Returns ["node"] for Claude (default) if agent is not found or has no ProcessNames.
|
||||
func GetProcessNames(agentName string) []string {
|
||||
info := GetAgentPresetByName(agentName)
|
||||
if info == nil || len(info.ProcessNames) == 0 {
|
||||
// Default to Claude's process name for backwards compatibility
|
||||
return []string{"node"}
|
||||
}
|
||||
return info.ProcessNames
|
||||
}
|
||||
|
||||
// MergeWithPreset applies preset defaults to a RuntimeConfig.
|
||||
// User-specified values take precedence over preset defaults.
|
||||
// Returns a new RuntimeConfig without modifying the original.
|
||||
|
||||
Reference in New Issue
Block a user