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
11 changes: 7 additions & 4 deletions docs/content/90.cli/2.commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ navigation:
使用 `veadk create` 命令在当前目录中创建一个新的智能体项目脚手架。

```bash
veadk create [OPTIONS]
veadk create [AGENT_NAME] [OPTIONS]
```

选项包括:
### 参数

- `AGENT_NAME`: 要创建的智能体的名称。如果未提供,将会提示您输入。

### 选项

- `--agent-name`:智能体的名称。如果未提供,将会提示您输入。
- `--ark-api-key`:ARK API 密钥。如果未提供,将会提示您输入或稍后在 `config.yaml` 文件中配置。

执行 `veadk create` 命令后,它会:

1. 提示您输入智能体名称(如果未通过 `--agent-name` 提供)。
1. 提示您输入智能体名称(如果未作为参数提供)。
2. 提示您输入 ARK API 密钥(如果未通过 `--ark-api-key` 提供),您可以选择立即输入或稍后在生成的 `config.yaml` 文件中手动配置。
3. 在当前目录下创建一个以智能体名称命名的新目录。
4. 在新目录中生成以下文件:
Expand Down
49 changes: 21 additions & 28 deletions tests/cli/test_cli_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,74 +20,67 @@
def test_create_agent_with_options():
runner = CliRunner()
with runner.isolated_filesystem() as temp_dir:
result = runner.invoke(
create, ["--agent-name", "test-agent", "--ark-api-key", "test-key"]
)
result = runner.invoke(create, ["test-agent", "--ark-api-key", "test-key"])
assert result.exit_code == 0

agent_folder = Path(temp_dir) / "test-agent"
assert agent_folder.exists()

config_path = agent_folder / "config.yaml"
config_path = agent_folder / ".env"
assert config_path.exists()
config_content = config_path.read_text()
assert "api_key: test-key" in config_content
assert "MODEL_AGENT_API_KEY=test-key" in config_content

agent_init_path = agent_folder / "test-agent" / "__init__.py"
agent_init_path = agent_folder / "__init__.py"
assert agent_init_path.exists()

agent_py_path = agent_folder / "test-agent" / "agent.py"
agent_py_path = agent_folder / "agent.py"
assert agent_py_path.exists()


def test_create_agent_overwrite_existing_directory():
runner = CliRunner()
with runner.isolated_filesystem() as temp_dir:
# First, create the agent
runner.invoke(
create, ["--agent-name", "test-agent", "--ark-api-key", "test-key"]
)
runner.invoke(create, ["test-agent", "--ark-api-key", "test-key"])

# Attempt to create it again, but cancel the overwrite
result = runner.invoke(
create,
["--agent-name", "test-agent", "--ark-api-key", "test-key"],
["test-agent", "--ark-api-key", "test-key"],
input="n\n",
)
assert "Operation cancelled" in result.output

# Attempt to create it again, and confirm the overwrite
result = runner.invoke(
create,
["--agent-name", "test-agent", "--ark-api-key", "new-key"],
["test-agent", "--ark-api-key", "new-key"],
input="y\n",
)
assert result.exit_code == 0
agent_folder = Path(temp_dir) / "test-agent"
config_path = agent_folder / "config.yaml"
config_path = agent_folder / ".env"
config_content = config_path.read_text()
assert "api_key: new-key" in config_content
assert "MODEL_AGENT_API_KEY=new-key" in config_content


def test_generate_files(tmp_path: Path):
agent_name = "test-agent"
api_key = "test-key"
target_dir = tmp_path / agent_name

_generate_files(agent_name, api_key, target_dir)

agent_code_dir = target_dir / agent_name
assert agent_code_dir.is_dir()
_generate_files(api_key, target_dir)

config_file = target_dir / "config.yaml"
config_file = target_dir / ".env"
assert config_file.is_file()
content = config_file.read_text()
assert f"api_key: {api_key}" in content
assert f"MODEL_AGENT_API_KEY={api_key}" in content

init_file = agent_code_dir / "__init__.py"
init_file = target_dir / "__init__.py"
assert init_file.is_file()

agent_file = agent_code_dir / "agent.py"
agent_file = target_dir / "agent.py"
assert agent_file.is_file()


Expand All @@ -96,15 +89,15 @@ def test_prompt_for_ark_api_key_enter_now():
with runner.isolated_filesystem():
result = runner.invoke(create, input="test-agent\n1\nmy-secret-key\n")
assert result.exit_code == 0
assert "my-secret-key" in (Path("test-agent") / "config.yaml").read_text()
assert "my-secret-key" in (Path("test-agent") / ".env").read_text()


def test_prompt_for_ark_api_key_configure_later():
runner = CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(create, input="test-agent\n2\n")
assert result.exit_code == 0
assert "api_key: " in (Path("test-agent") / "config.yaml").read_text()
assert "MODEL_AGENT_API_KEY=" in (Path("test-agent") / ".env").read_text()


def test_create_agent_with_prompts():
Expand All @@ -116,13 +109,13 @@ def test_create_agent_with_prompts():
agent_folder = Path(temp_dir) / "test-agent"
assert agent_folder.exists()

config_path = agent_folder / "config.yaml"
config_path = agent_folder / ".env"
assert config_path.exists()
config_content = config_path.read_text()
assert "api_key: test-key" in config_content
assert "MODEL_AGENT_API_KEY=test-key" in config_content

agent_init_path = agent_folder / "test-agent" / "__init__.py"
agent_init_path = agent_folder / "__init__.py"
assert agent_init_path.exists()

agent_py_path = agent_folder / "test-agent" / "agent.py"
agent_py_path = agent_folder / "agent.py"
assert agent_py_path.exists()
60 changes: 20 additions & 40 deletions veadk/cli/cli_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,8 @@
import shutil
from pathlib import Path

_CONFIG_YAML_TEMPLATE = """\
model:
agent:
name: doubao-seed-1-6-251015
api_key: {ark_api_key}
video:
name: doubao-seedance-1-0-pro-250528
# if you want to use different api_key, just uncomment following line and complete api_key
# api_key:
image:
name: doubao-seedream-4-0-250828
# if you want to use different api_key, just uncomment following line and complete api_key
# api_key:

logging:
# ERROR
# WARNING
# INFO
# DEBUG
level: DEBUG
_ENV_TEMPLATE = """\
MODEL_AGENT_API_KEY={ark_api_key}
"""

_INIT_PY_TEMPLATE = """\
Expand All @@ -49,16 +31,17 @@
name="root_agent",
description="A helpful assistant for user questions.",
instruction="Answer user questions to the best of your knowledge",
model_name="doubao-seed-1-6-251015", # <---- you can change your model here
)
"""

_SUCCESS_MSG = """\
Agent '{agent_name}' created successfully at '{agent_folder}':
- config.yaml
- {agent_name}/__init__.py
- {agent_name}/agent.py
Agent created in {agent_folder}:
- .env
- __init__.py
- agent.py

You can run the agent by executing: cd {agent_name} && veadk web
You can run the agent by executing: veadk web
"""


Expand All @@ -69,37 +52,34 @@ def _prompt_for_ark_api_key() -> str:
)
click.echo("You have two options:")
click.echo(" 1. Enter the API key now.")
click.echo(" 2. Configure it later in the generated config.yaml file.")
click.echo(" 2. Configure it later in the generated .env file.")
choice = click.prompt("Please select an option", type=click.Choice(["1", "2"]))
if choice == "1":
return click.prompt("Please enter your ARK API key")
else:
click.secho(
"You can set the `api_key` in the config.yaml file later.", fg="yellow"
)
click.secho("You can set the `api_key` in the .env file later.", fg="yellow")
return ""


def _generate_files(agent_name: str, ark_api_key: str, target_dir_path: Path) -> None:
agent_dir_path = target_dir_path / agent_name
agent_dir_path.mkdir(parents=True, exist_ok=True)
config_yaml_path = target_dir_path / "config.yaml"
init_file_path = agent_dir_path / "__init__.py"
agent_file_path = agent_dir_path / "agent.py"
def _generate_files(ark_api_key: str, target_dir_path: Path) -> None:
target_dir_path.mkdir(exist_ok=True)
env_path = target_dir_path / ".env"
init_file_path = target_dir_path / "__init__.py"
agent_file_path = target_dir_path / "agent.py"

config_yaml_content = _CONFIG_YAML_TEMPLATE.format(ark_api_key=ark_api_key)
config_yaml_path.write_text(config_yaml_content)
env_content = _ENV_TEMPLATE.format(ark_api_key=ark_api_key)
env_path.write_text(env_content)
init_file_path.write_text(_INIT_PY_TEMPLATE)
agent_file_path.write_text(_AGENT_PY_TEMPLATE)

click.secho(
_SUCCESS_MSG.format(agent_name=agent_name, agent_folder=target_dir_path),
_SUCCESS_MSG.format(agent_folder=target_dir_path),
fg="green",
)


@click.command()
@click.option("--agent-name", help="The name of the agent.")
@click.argument("agent_name", required=False)
@click.option("--ark-api-key", help="The ARK API key.")
def create(agent_name: str, ark_api_key: str) -> None:
"""Creates a new agent in the current folder with prepopulated agent template."""
Expand All @@ -119,4 +99,4 @@ def create(agent_name: str, ark_api_key: str) -> None:
return
shutil.rmtree(target_dir_path)

_generate_files(agent_name, ark_api_key, target_dir_path)
_generate_files(ark_api_key, target_dir_path)