Closes #5
This PR implements a GitHub Copilot CLI adapter as requested in issue #5, following the same interface pattern as the existing Codex adapter. Additionally, it introduces a mock adapter for testing without external dependencies and implements adapter selection via environment variables.
- Implements
CopilotCLIAdapter,CopilotCLIError, andCopilotResultclasses - Mirrors the Codex adapter interface for consistency
- Supports JSONL event parsing and plaintext fallback
- Configurable via environment variables:
AGENTFLOW_COPILOT_PATH— CLI binary path (default:copilot)AGENTFLOW_COPILOT_TOKEN— optional auth token
- Full documentation in
src/agentflow/adapters/COPILOT_README.md
- Zero-dependency adapter for testing and demos
- Returns canned responses without external CLI calls
- Generates synthetic flow specs for flow-related prompts
- Ideal for CI/CD, unit tests, and quick demos
- CLI now reads
AGENTFLOW_ADAPTERenvironment variable - Supported values:
codex(default),copilot,mock - Graceful error handling for all adapter types
- Example usage:
# Use Copilot adapter export AGENTFLOW_ADAPTER=copilot agentflow "Your prompt here" # Use mock adapter for testing export AGENTFLOW_ADAPTER=mock agentflow "Test prompt"
- ✅ Tests JSONL event parsing with mocked subprocess
- ✅ Tests error handling for non-zero exit codes
- ✅ All 7 unit tests passing (Codex + Copilot adapters)
- Uses same test pattern as existing Codex adapter tests
pytest tests/unit -q
# 7 passed in 0.26s-
ADAPTERS.md— Comprehensive adapter usage guide- Detailed examples for all three adapters
- Configuration reference
- Common tasks and troubleshooting
- PowerShell and Bash examples
-
src/agentflow/adapters/COPILOT_README.md— Copilot adapter quick reference- Installation and configuration
- Python API examples
- Notes on output format compatibility
- Added
copilot_cli_pathfield (default:"copilot") - Added
copilot_tokenoptional field - Environment variable mapping:
AGENTFLOW_COPILOT_PATH→copilot_cli_pathAGENTFLOW_COPILOT_TOKEN→copilot_token
- Removed unsupported Cytoscape shadow properties (
shadow-blur,shadow-color,shadow-offset-x,shadow-offset-y) - Eliminates browser console warnings
- No visual regression — viewer remains fully functional
- Changed prompt passing from stdin to CLI argument
- Improves testability and aligns with expected invocation pattern
- Maintains backward compatibility
- Added
CopilotCLIAdapter,CopilotCLIError,CopilotResult - Added
MockAdapter,MockAdapterError,MockResult - All adapters now properly exported and importable
# No external dependencies required
$env:AGENTFLOW_ADAPTER = "mock"
$env:OPENAI_API_KEY = "test"
python -m agentflow.cli "Create a simple flow that says hello"
# View generated artifacts in browser
python -m agentflow.cli view --directory . --port 5050
# Open http://127.0.0.1:5050# Configure Copilot adapter
$env:AGENTFLOW_ADAPTER = "copilot"
$env:AGENTFLOW_COPILOT_PATH = "path/to/copilot"
$env:AGENTFLOW_COPILOT_TOKEN = "your-token"
$env:OPENAI_API_KEY = "dummy" # required by config but not used
# Run CLI
python -m agentflow.cli "Generate a Python function to sort a list"# Use Codex (default)
export AGENTFLOW_ADAPTER=codex
agentflow "prompt"
# Switch to Copilot
export AGENTFLOW_ADAPTER=copilot
agentflow "prompt"
# Switch to Mock for testing
export AGENTFLOW_ADAPTER=mock
agentflow "prompt"# Install dev dependencies
pip install -e ".[dev]"
# Run all unit tests
pytest tests/unit -q
# Run specific adapter tests
pytest tests/unit/test_copilot_adapter.py -v# Test mock adapter (no external deps)
export AGENTFLOW_ADAPTER=mock
export OPENAI_API_KEY=test
python -m agentflow.cli "Create a workflow with 3 steps"
# Verify artifact was created
ls -la agentflow-*.yaml
# Start viewer and inspect
python -m agentflow.cli view --directory . --port 5050All adapters implement the same interface for consistency:
class Adapter:
def __init__(self, settings: Settings, extra_args: Optional[Iterable[str]] = None):
...
def run(self, prompt: str, *, timeout: int = 120, cwd: Optional[str] = None) -> Result:
...
@dataclass
class Result:
message: str # Assistant's text response
events: List[Dict] # JSONL event list (if any)
usage: Dict # Token usage metrics-
Adapter Selection via Environment Variable
- Simple, flexible configuration
- No CLI breaking changes required
- Easy to switch in CI/CD pipelines
-
Mock Adapter Benefits
- Enables testing without API keys
- Fast artifact generation for demos
- Consistent synthetic data for docs
-
Maintained Backward Compatibility
- Codex remains the default adapter
- Existing workflows unchanged
- New features are opt-in
The mock adapter generates flow artifacts that render perfectly in the viewer:
- Sidebar: Lists all generated plan artifacts
- Graph: Interactive DAG showing nodes (start → greet → end)
- Details Panel: Click nodes to inspect prompts, responses, and flow specs
- Removed browser console warnings (Cytoscape shadow properties)
- Clean, warning-free rendering
- All interactive features working
- Implemented Copilot CLI adapter
- Implemented Mock adapter for testing
- Added adapter selection system (environment variable)
- Added unit tests (mocked subprocess)
- All tests passing (7/7)
- Added comprehensive documentation (ADAPTERS.md)
- Added usage examples and config snippets
- Exported new adapters from package
- Fixed viewer console warnings
- Updated Settings configuration
- Maintained backward compatibility
- No breaking changes to existing API
Closes #5 — Implement a Copilot CLI adapter as an AgentFlow CLI agent adapter
None. This PR is fully backward compatible:
- Codex adapter remains the default
- Existing CLI workflows continue to work
- New adapters are opt-in via environment variable
Potential follow-ups (not in scope for this PR):
- Live integration tests with real Copilot CLI (marked with
@pytest.mark.live) - Additional adapters (Anthropic Claude, Google Gemini, etc.)
- Adapter-specific configuration profiles in
.envor config files - Adapter health checks and diagnostics command
Thanks to @stancsz for the clear feature request and issue description!