Enable cli options for plugin (#22)

* added the entry point for plugin with cli group option
This commit is contained in:
Lifei Zhou
2024-08-29 09:03:12 +10:00
committed by GitHub
parent 5aa12ec9ed
commit 6fef25aa62
3 changed files with 62 additions and 11 deletions

View File

@@ -1,7 +1,7 @@
[project]
name = "goose-ai"
description = "a programming agent that runs on your machine"
version = "0.8.0"
version = "0.8.1"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
@@ -30,9 +30,11 @@ default = "goose.profile:default_profile"
[project.entry-points."goose.command"]
file = "goose.command.file:FileCommand"
[project.entry-points."goose.cli"]
[project.entry-points."goose.cli.group"]
goose = "goose.cli.main:goose_cli"
[project.entry-points."goose.cli.group_option"]
[project.scripts]
goose = "goose.cli.main:cli"

View File

@@ -12,12 +12,10 @@ from goose.cli.session import Session
from goose.utils import load_plugins
from goose.utils.session_file import list_sorted_session_files
@click.group()
def goose_cli() -> None:
pass
@goose_cli.command()
def version() -> None:
"""Lists the version of goose and any plugins"""
@@ -81,7 +79,7 @@ def session_start(profile: str, plan: Optional[str] = None) -> None:
@session.command(name="resume")
@click.argument("name", required=False)
@click.option("--profile")
def session_resume(name: str, profile: str) -> None:
def session_resume(name: Optional[str], profile: str) -> None:
"""Resume an existing goose session"""
if name is None:
session_files = get_session_files()
@@ -97,6 +95,7 @@ def session_resume(name: str, profile: str) -> None:
@session.command(name="list")
def session_list() -> None:
"""List goose sessions"""
session_files = get_session_files().items()
for session_name, session_file in session_files:
print(f"{datetime.fromtimestamp(session_file.stat().st_mtime).strftime('%Y-%m-%d %H:%M:%S')} {session_name}")
@@ -105,6 +104,7 @@ def session_list() -> None:
@session.command(name="clear")
@click.option("--keep", default=3, help="Keep this many entries, default 3")
def session_clear(keep: int) -> None:
"""Delete old goose sessions, keeping the most recent sessions up to the specified number"""
for i, (_, session_file) in enumerate(get_session_files().items()):
if i >= keep:
session_file.unlink()
@@ -113,13 +113,22 @@ def session_clear(keep: int) -> None:
def get_session_files() -> Dict[str, Path]:
return list_sorted_session_files(SESSIONS_PATH)
@click.group(
invoke_without_command=True,
name="goose",
help="AI-powered tool to assist in solving programming and operational tasks",)
@click.pass_context
def cli(_: click.Context, **kwargs: Dict) -> None:
pass
# merging goose cli with additional cli plugins.
def cli() -> None:
clis = load_plugins("goose.cli")
cli_list = list(clis.values()) or []
click.CommandCollection(sources=cli_list)()
all_cli_group_options = load_plugins("goose.cli.group_option")
for option in all_cli_group_options.values():
cli = option()(cli)
all_cli_groups = load_plugins("goose.cli.group")
for group in all_cli_groups.values():
for command in group.commands.values():
cli.add_command(command)
if __name__ == "__main__":
cli()

View File

@@ -1,11 +1,13 @@
from datetime import datetime
import importlib
from time import time
from unittest.mock import MagicMock, patch
import click
import pytest
from click.testing import CliRunner
from exchange import Message
from goose.cli.main import goose_cli
from goose.cli.main import cli, goose_cli
@pytest.fixture
@@ -78,3 +80,41 @@ def test_session_clear_command(mock_session_files_path, create_session_file):
session_files = list(mock_session_files_path.glob("*.jsonl"))
assert len(session_files) == 1
assert session_files[0].stem == "second"
def test_combined_group_option():
with patch("goose.utils.load_plugins") as mock_load_plugin:
group_option_name = "--describe-commands"
def option_callback(ctx, *_):
click.echo("Option callback")
ctx.exit()
mock_group_options = {
'option1': lambda: click.option(
group_option_name,
is_flag=True,
callback=option_callback,
),
}
def side_effect_func(param):
if param == "goose.cli.group_option":
return mock_group_options
elif param == "goose.cli.group":
return { }
mock_load_plugin.side_effect = side_effect_func
# reload cli after mocking
importlib.reload(importlib.import_module('goose.cli.main'))
import goose.cli.main
cli = goose.cli.main.cli
runner = CliRunner()
result = runner.invoke(cli, [group_option_name])
assert result.exit_code == 0
def test_combined_group_commands(mock_session):
mock_session_class, mock_session_instance = mock_session
runner = CliRunner()
runner.invoke(cli, ["session", "resume", "session1", "--profile", "default"])
mock_session_class.assert_called_once_with(name="session1", profile="default")
mock_session_instance.run.assert_called_once()