Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions src/specify_cli/integrations/agy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
"""Antigravity (agy) integration — skills-based agent.

Antigravity uses ``.agent/skills/speckit-<name>/SKILL.md`` layout.
Explicit command support was deprecated in version 1.20.5;
``--skills`` defaults to ``True``.
Antigravity uses ``.agents/skills/speckit-<name>/SKILL.md`` layout (enforced since v1.20.5).
"""

from __future__ import annotations

from ..base import IntegrationOption, SkillsIntegration
from pathlib import Path
from typing import TYPE_CHECKING, Any

from ..base import SkillsIntegration

if TYPE_CHECKING:
from ..manifest import IntegrationManifest



class AgyIntegration(SkillsIntegration):
Expand All @@ -16,26 +21,32 @@ class AgyIntegration(SkillsIntegration):
key = "agy"
config = {
"name": "Antigravity",
"folder": ".agent/",
"folder": ".agents/",
Comment thread
baveku marked this conversation as resolved.
"commands_subdir": "skills",
"install_url": None,
"requires_cli": False,
}
registrar_config = {
"dir": ".agent/skills",
"dir": ".agents/skills",
"format": "markdown",
"args": "$ARGUMENTS",
"extension": "/SKILL.md",
}
context_file = "AGENTS.md"

@classmethod
def options(cls) -> list[IntegrationOption]:
return [
IntegrationOption(
"--skills",
is_flag=True,
default=True,
help="Install as agent skills (default for Antigravity since v1.20.5)",
),
]
def setup(
self,
project_root: Path,
manifest: IntegrationManifest,
parsed_options: dict[str, Any] | None = None,
**opts: Any,
) -> list[Path]:
import click

click.secho(
"Warning: The .agents/ layout requires Antigravity v1.20.5 or newer. "
"Please ensure your agy installation is up to date.",
fg="yellow",
err=True,
)
return super().setup(project_root, manifest, parsed_options=parsed_options, **opts)
Comment thread
mnriem marked this conversation as resolved.
Comment thread
mnriem marked this conversation as resolved.
26 changes: 22 additions & 4 deletions tests/integrations/test_integration_agy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@

class TestAgyIntegration(SkillsIntegrationTests):
KEY = "agy"
FOLDER = ".agent/"
FOLDER = ".agents/"
COMMANDS_SUBDIR = "skills"
REGISTRAR_DIR = ".agent/skills"
REGISTRAR_DIR = ".agents/skills"
CONTEXT_FILE = "AGENTS.md"


def test_options_include_skills_flag(self):
"""Override inherited test: AgyIntegration should not expose a --skills flag because .agents/ is its only layout."""
from specify_cli.integrations import get_integration
i = get_integration(self.KEY)
skills_opts = [o for o in i.options() if o.name == "--skills"]
assert len(skills_opts) == 0
class TestAgyAutoPromote:
"""--ai agy auto-promotes to integration path."""

Expand All @@ -24,4 +29,17 @@ def test_ai_agy_without_ai_skills_auto_promotes(self, tmp_path):
result = runner.invoke(app, ["init", str(target), "--ai", "agy", "--no-git", "--script", "sh"])

assert result.exit_code == 0, f"init --ai agy failed: {result.output}"
assert (target / ".agent" / "skills" / "speckit-plan" / "SKILL.md").exists()
assert (target / ".agents" / "skills" / "speckit-plan" / "SKILL.md").exists()

def test_agy_setup_warning(self, tmp_path):
"""Agy integration should print a warning about v1.20.5 requirement during setup."""
from typer.testing import CliRunner
from specify_cli import app

# Click >= 8.2 separates stdout and stderr natively, mix_stderr is removed
runner = CliRunner()
target = tmp_path / "test-proj2"
result = runner.invoke(app, ["init", str(target), "--ai", "agy", "--no-git", "--script", "sh"])

assert result.exit_code == 0
assert "Warning: The .agents/ layout requires Antigravity v1.20.5 or newer" in result.stderr
2 changes: 1 addition & 1 deletion tests/test_presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2447,7 +2447,7 @@ def test_kimi_preset_skill_override_resolves_script_placeholders(self, project_d
def test_agy_skill_restored_on_preset_remove(self, project_dir, temp_dir):
"""Agy preset removal should restore native skills instead of deleting them."""
self._write_init_options(project_dir, ai="agy", ai_skills=True)
skills_dir = project_dir / ".agent" / "skills"
skills_dir = project_dir / ".agents" / "skills"
self._create_skill(skills_dir, "speckit-specify", body="before override")

core_command = project_dir / ".specify" / "templates" / "commands" / "specify.md"
Expand Down
Loading