Skip to content
Open
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
32 changes: 32 additions & 0 deletions src/specify_cli/integrations/amp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""Amp CLI integration."""

from collections.abc import Mapping, Sequence
from typing import Any

from ..base import MarkdownIntegration


Expand All @@ -18,3 +21,32 @@ class AmpIntegration(MarkdownIntegration):
"args": "$ARGUMENTS",
"extension": ".md",
}

def build_exec_args(
self,
prompt: str,
*,
model: str | None = None,
output_json: bool = True,
integration_args: Sequence[str] | None = None,
integration_options: Mapping[str, Any] | None = None,
) -> list[str] | None:
self.validate_runtime_config(integration_args, integration_options)
args = [self._resolve_executable()]
# Operator-injected extra args go before --execute: the flag takes the
# prompt as an optional inline value, so anything appended between the
# two would be consumed as the message instead.
self._apply_extra_args_env_var(args)

args.extend(["--execute", prompt])

if output_json:
# Amp's structured output is --stream-json (Claude Code-compatible
# stream JSON), valid only alongside --execute.
args.append("--stream-json")

# `model` is deliberately dropped: Amp has no model-selection flag.
# `-m/--mode` takes an agent mode (low/medium/high/ultra or a plugin
# mode), not a model identifier, so forwarding the caller's model onto
# it would silently select the wrong thing.
return args
74 changes: 74 additions & 0 deletions tests/integrations/test_integration_amp.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Tests for AmpIntegration."""

from specify_cli.integrations import get_integration

from .test_integration_base_markdown import MarkdownIntegrationTests


Expand All @@ -8,3 +10,75 @@ class TestAmpIntegration(MarkdownIntegrationTests):
FOLDER = ".agents/"
COMMANDS_SUBDIR = "commands"
REGISTRAR_DIR = ".agents/commands"

def test_build_exec_args_uses_execute_mode(self):
"""Amp dispatches through execute mode, not the inherited `-p`.

The Amp CLI has no `-p`/`--prompt` flag; passing one aborts with
`error: unknown option '-p'` before the agent runs (#4580).
"""
integration = get_integration(self.KEY)

args = integration.build_exec_args(
"/speckit.specify build a login page",
output_json=False,
)

assert args == [
"amp",
"--execute",
"/speckit.specify build a login page",
]
assert "-p" not in args

def test_build_exec_args_requests_stream_json(self):
"""`--stream-json` is Amp's structured-output flag, used with --execute."""
integration = get_integration(self.KEY)

args = integration.build_exec_args("/speckit.plan add OAuth", output_json=True)

assert args == [
"amp",
"--execute",
"/speckit.plan add OAuth",
"--stream-json",
]
assert "--output-format" not in args

def test_build_exec_args_omits_model_flag(self):
"""Amp exposes no model-selection flag, so `model` is not forwarded.

`-m/--mode` takes an agent mode (low/medium/high/ultra), not a model
identifier, so remapping the caller's model onto it would be wrong.
"""
integration = get_integration(self.KEY)

args = integration.build_exec_args(
"explain this repository",
model="gpt-5",
output_json=False,
)

assert args == ["amp", "--execute", "explain this repository"]
assert "--model" not in args
assert "-m" not in args
assert "gpt-5" not in args

def test_build_exec_args_applies_extra_args_before_execute(self, monkeypatch):
"""Operator-injected flags precede `--execute` so they stay global.

`--execute [message]` takes the prompt as an optional inline value, so
injecting between the flag and the prompt would consume the prompt.
"""
monkeypatch.setenv("SPECKIT_INTEGRATION_AMP_EXTRA_ARGS", "--no-notifications")
integration = get_integration(self.KEY)

args = integration.build_exec_args("check the build", output_json=True)

assert args == [
"amp",
"--no-notifications",
"--execute",
"check the build",
"--stream-json",
]
Loading