Add `cli_executable` property to `IntegrationBase` for agents whose executable differs from their key
- 主要言語
- Python
- スター
- 137k
- フォーク
- 12.3k
- 平均マージ
- 2日 12時間
- マージ済み PR(30日)
- 159
説明
**Blocked by:** #2539
## Problem
The integration framework assumes `key == CLI executable name` — `shutil.which(impl.key)` is used at three detection sites. This breaks for agents like Rovo Dev where the key is `rovodev` but the executable is `acli` (invoked as `acli rovodev`).
Today there are two hardcoded special cases in `check_tool()` for similar mismatches:
- **Claude** — checks `~/.claude/local/claude` and npm-local paths outside PATH
- **kiro-cli** — falls back to `shutil.which("kiro")` when `kiro-cli` isn't found
Adding more special cases is not sustainable.
## Proposed Solution
Add a `cli_executable` property to `IntegrationBase`:
```python
@property
def cli_executable(self) -> str:
"""Executable name for CLI detection. Defaults to key."""
return self.key
```
Update the three detection sites to use it:
- `src/specify_cli/workflows/steps/command/__init__.py` — `shutil.which(impl.cli_executable)`
- `src/specify_cli/workflows/steps/prompt/__init__.py` — `shutil.which(impl.cli_executable)`
- `src/specify_cli/_utils.py` `check_tool()` — resolve integration, use `impl.cli_executable`
## Integration Overrides
**Rovodev** — executable is `acli`:
```python
@property
def cli_executable(self) -> str:
return "acli"
```
**Kiro-CLI** — override to try both names, removing the hardcoded branch in `check_tool()`:
```python
@property
def cli_executable(self) -> str:
return "kiro-cli"
```
**Claude** — local path checks move into the integration class (e.g. override an `is_cli_available()` method), removing the hardcoded branch in `check_tool()`.
## Design Note
If kiro-cli's dual-binary case and Claude's non-PATH local installs are awkward to express with a single `cli_executable` string, consider either:
- A `cli_executables` list property (check any match)
- An `is_cli_available() -> bool` method that integrations override for custom detection, with the default implementation doing `shutil.which(self.cli_executable)`
The latter is more flexible and handles Claude's path checks cleanly.
## Acceptance Criteria
- [ ] #2539 merged first (rovodev integration scaffolding)
- [ ] `cli_executable` property (or `is_cli_available()`) on `IntegrationBase`
- [ ] Three detection sites use the new mechanism
- [ ] Rovodev dispatch works with `acli` executable
- [ ] Claude and kiro-cli special cases removed from `check_tool()`
- [ ] Existing tests pass; new tests cover the override behavior
- [ ] `AGENTS.md` updated to document `cli_executable` / `is_cli_available()` override
## Context
Follow-up from #2539 (rovodev integration). The integration scaffolding merged without dispatch support; this consolidates all CLI detection into a single extensible mechanism.
コントリビューションガイド
評価
この issue はまだ評価されていません。