Skip to content

Commit 45ee9da

Browse files
committed
use cookiecutter for template
1 parent 33938cf commit 45ee9da

File tree

18 files changed

+166
-175
lines changed

18 files changed

+166
-175
lines changed

pyproject.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ cli = [
4343
"volcengine-python-sdk==4.0.3", # For Volcengine API
4444
"agent-pilot-sdk>=0.0.9", # Prompt optimization by Volcengine AgentPilot/PromptPilot toolkits
4545
"fastmcp>=2.11.3", # For running MCP
46+
"cookiecutter>=2.6.0", # For cloud deploy
4647
]
4748
dev = [
4849
"pre-commit>=4.2.0", # Format checking
@@ -69,4 +70,9 @@ exclude = ["assets*", "ide*", "tests*"]
6970
include-package-data = true
7071

7172
[tool.setuptools.package-data]
72-
"veadk" = ["**/*"]
73+
"veadk" = ["**/*"]
74+
75+
[tool.ruff]
76+
exclude = [
77+
"veadk/integrations/ve_faas/template/*"
78+
]

veadk/cli/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
from veadk.cli.cli_init import init
1919
from veadk.cli.cli_prompt import prompt
2020
from veadk.cli.cli_web import web
21+
from veadk.utils.logger import get_logger
2122
from veadk.version import VERSION
2223

24+
logger = get_logger(__name__)
25+
2326

2427
@click.group()
2528
@click.version_option(

veadk/cli/cli_deploy.py

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
import click
1616

17+
TEMP_PATH = "/tmp"
18+
1719

1820
@click.command()
1921
@click.option(
@@ -26,21 +28,96 @@
2628
default=None,
2729
help="Volcengine secret key",
2830
)
29-
@click.option("--name", help="Expected Volcengine FaaS application name")
31+
@click.option("--vefaas-app-name", help="Expected Volcengine FaaS application name")
32+
@click.option("--veapig-instance-name", help="Expected Volcengine APIG instance name")
33+
@click.option("--veapig-service-name", help="Expected Volcengine APIG service name")
34+
@click.option("--veapig-upstream-name", help="Expected Volcengine APIG upstream name")
35+
@click.option(
36+
"--short-term-memory-backend",
37+
default="local",
38+
type=click.Choice(["local", "mysql"]),
39+
help="Backend for short-term memory",
40+
)
41+
@click.option("--use-adk-web", is_flag=True, help="Whether to use ADK Web")
3042
@click.option("--path", default=".", help="Local project path")
31-
def deploy(access_key: str, secret_key: str, name: str, path: str) -> None:
43+
def deploy(
44+
access_key: str,
45+
secret_key: str,
46+
vefaas_app_name: str,
47+
veapig_instance_name: str,
48+
veapig_service_name: str,
49+
veapig_upstream_name: str,
50+
short_term_memory_backend: str,
51+
use_adk_web: bool,
52+
path: str,
53+
) -> None:
3254
"""Deploy a user project to Volcengine FaaS application."""
55+
import shutil
3356
from pathlib import Path
3457

58+
from cookiecutter.main import cookiecutter
59+
60+
import veadk.integrations.ve_faas as vefaas
3561
from veadk.config import getenv
36-
from veadk.integrations.ve_faas.ve_faas import VeFaaS
62+
from veadk.utils.misc import formatted_timestamp
3763

3864
if not access_key:
3965
access_key = getenv("VOLCENGINE_ACCESS_KEY")
4066
if not secret_key:
4167
secret_key = getenv("VOLCENGINE_SECRET_KEY")
4268

4369
user_proj_abs_path = Path(path).resolve()
70+
template_dir_path = Path(vefaas.__file__).parent / "template"
71+
72+
tmp_dir_name = f"{user_proj_abs_path.name}_{formatted_timestamp()}"
73+
74+
settings = {
75+
"local_dir_name": tmp_dir_name,
76+
"app_name": user_proj_abs_path.name,
77+
"agent_module_name": user_proj_abs_path.name,
78+
"requirement_file_path": str(user_proj_abs_path / "requirements.txt"),
79+
"short_term_memory_backend": short_term_memory_backend,
80+
"vefaas_application_name": vefaas_app_name,
81+
"veapig_instance_name": veapig_instance_name,
82+
"veapig_service_name": veapig_service_name,
83+
"veapig_upstream_name": veapig_upstream_name,
84+
"use_adk_web": use_adk_web,
85+
}
86+
87+
print(settings)
88+
89+
cookiecutter(
90+
template=str(template_dir_path),
91+
output_dir=TEMP_PATH,
92+
no_input=True,
93+
extra_context=settings,
94+
)
95+
96+
agent_dir = (
97+
Path(TEMP_PATH)
98+
/ tmp_dir_name
99+
/ "src"
100+
/ user_proj_abs_path.name.replace("-", "_")
101+
)
102+
103+
# remove /tmp/tmp_dir_name/src/user_proj_abs_path.name
104+
shutil.rmtree(agent_dir)
105+
agent_dir.mkdir(parents=True, exist_ok=True)
106+
107+
# mv
108+
shutil.copytree(user_proj_abs_path, agent_dir, dirs_exist_ok=True)
109+
110+
# mv requirements.txt and config.yaml if have
111+
if (user_proj_abs_path / "requirements.txt").exists():
112+
shutil.copy(
113+
user_proj_abs_path / "requirements.txt",
114+
f"{TEMP_PATH}/{tmp_dir_name}/requirements.txt",
115+
)
116+
# remove file
44117

45-
ve_faas = VeFaaS(access_key=access_key, secret_key=secret_key)
46-
ve_faas.deploy(name=name, path=str(user_proj_abs_path))
118+
if (user_proj_abs_path / "config.yaml").exists():
119+
shutil.copy(
120+
user_proj_abs_path / "config.yaml",
121+
f"{TEMP_PATH}/{tmp_dir_name}/config.yaml",
122+
)
123+
# remove file

veadk/cli/cli_init.py

Lines changed: 4 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,97 +12,20 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import Any
16-
1715
import click
1816

1917

20-
def _set_variable_in_file(file_path: str, setting_values: dict):
21-
import ast
22-
23-
with open(file_path, "r", encoding="utf-8") as f:
24-
source_code = f.read()
25-
26-
tree = ast.parse(source_code)
27-
28-
class VariableTransformer(ast.NodeTransformer):
29-
def visit_Assign(self, node: ast.Assign):
30-
for target in node.targets:
31-
if isinstance(target, ast.Name) and target.id in setting_values:
32-
node.value = ast.Constant(value=setting_values[target.id])
33-
return node
34-
35-
transformer = VariableTransformer()
36-
new_tree = transformer.visit(tree)
37-
ast.fix_missing_locations(new_tree)
38-
new_source_code = ast.unparse(new_tree)
39-
40-
with open(file_path, "w", encoding="utf-8") as f:
41-
f.write(new_source_code)
42-
43-
click.echo("Your project has beed created.")
44-
45-
46-
def _render_prompts() -> dict[str, Any]:
47-
vefaas_application_name = click.prompt(
48-
"Volcengine FaaS application name", default="veadk-cloud-agent"
49-
)
50-
51-
gateway_name = click.prompt(
52-
"Volcengine gateway instance name", default="", show_default=True
53-
)
54-
55-
gateway_service_name = click.prompt(
56-
"Volcengine gateway service name", default="", show_default=True
57-
)
58-
59-
gateway_upstream_name = click.prompt(
60-
"Volcengine gateway upstream name", default="", show_default=True
61-
)
62-
63-
deploy_mode_options = {
64-
"1": "A2A/MCP Server",
65-
"2": "VeADK Web / Google ADK Web",
66-
}
67-
68-
click.echo("Choose a deploy mode:")
69-
for key, value in deploy_mode_options.items():
70-
click.echo(f" {key}. {value}")
71-
72-
deploy_mode = click.prompt(
73-
"Enter your choice", type=click.Choice(deploy_mode_options.keys())
74-
)
75-
76-
return {
77-
"VEFAAS_APPLICATION_NAME": vefaas_application_name,
78-
"GATEWAY_NAME": gateway_name,
79-
"GATEWAY_SERVICE_NAME": gateway_service_name,
80-
"GATEWAY_UPSTREAM_NAME": gateway_upstream_name,
81-
"USE_ADK_WEB": deploy_mode == deploy_mode_options["2"],
82-
}
83-
84-
8518
@click.command()
8619
def init() -> None:
8720
"""Init a veadk project that can be deployed to Volcengine VeFaaS."""
88-
import shutil
8921
from pathlib import Path
9022

23+
from cookiecutter.main import cookiecutter
24+
9125
import veadk.integrations.ve_faas as vefaas
9226

9327
cwd = Path.cwd()
94-
local_dir_name = click.prompt("Directory name", default="veadk-cloud-proj")
95-
target_dir_path = cwd / local_dir_name
96-
97-
if target_dir_path.exists():
98-
click.confirm(
99-
f"Directory '{target_dir_path}' already exists, do you want to overwrite it",
100-
abort=True,
101-
)
102-
shutil.rmtree(target_dir_path)
103-
104-
setting_values = _render_prompts()
10528

10629
template_dir_path = Path(vefaas.__file__).parent / "template"
107-
shutil.copytree(template_dir_path, target_dir_path)
108-
_set_variable_in_file(target_dir_path / "deploy.py", setting_values)
30+
31+
cookiecutter(template=str(template_dir_path), output_dir=str(cwd))

veadk/cloud/cloud_agent_engine.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import os
16+
import shutil
1617
import socket
1718
import subprocess
1819
import time
@@ -66,29 +67,29 @@ def _prepare(self, path: str, name: str):
6667
)
6768

6869
# prepare template files if not have
69-
template_files = [
70-
"app.py",
71-
"run.sh",
72-
# "requirements.txt",
73-
"__init__.py",
74-
]
75-
for template_file in template_files:
76-
if os.path.exists(os.path.join(path, template_file)):
77-
logger.warning(
78-
f"Local agent project path `{path}` contains a `{template_file}` file. Use your own `{template_file}` file may cause unexpected behavior."
79-
)
80-
else:
81-
logger.info(
82-
f"No `{template_file}` detected in local agent project path `{path}`. Prepare it."
83-
)
84-
import veadk.integrations.ve_faas as vefaas
85-
86-
template_file_path = (
87-
Path(vefaas.__file__).parent / "template" / "src" / template_file
88-
)
89-
import shutil
90-
91-
shutil.copy(template_file_path, os.path.join(path, template_file))
70+
# template_files = [
71+
# "app.py",
72+
# "run.sh",
73+
# # "requirements.txt",
74+
# "__init__.py",
75+
# ]
76+
# for template_file in template_files:
77+
# if os.path.exists(os.path.join(path, template_file)):
78+
# logger.warning(
79+
# f"Local agent project path `{path}` contains a `{template_file}` file. Use your own `{template_file}` file may cause unexpected behavior."
80+
# )
81+
# else:
82+
# logger.info(
83+
# f"No `{template_file}` detected in local agent project path `{path}`. Prepare it."
84+
# )
85+
# import veadk.integrations.ve_faas as vefaas
86+
87+
# template_file_path = (
88+
# Path(vefaas.__file__).parent / "template" / "src" / template_file
89+
# )
90+
# import shutil
91+
92+
# shutil.copy(template_file_path, os.path.join(path, template_file))
9293

9394
# copy user's requirements.txt
9495
if os.path.exists(os.path.join(path, "requirements.txt")):

veadk/integrations/ve_faas/template/README.md

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"local_dir_name": "veadk_vefaas_proj",
3+
"app_name": "weather-report",
4+
"agent_module_name": "weather_agent",
5+
"requirement_file_path": "./weather_agent/requirements.txt",
6+
"short_term_memory_backend": "local",
7+
"vefaas_application_name": "weather-reporter",
8+
"veapig_instance_name": "",
9+
"veapig_service_name": "",
10+
"veapig_upstream_name": "",
11+
"use_adk_web": false
12+
}

veadk/integrations/ve_faas/template/__init__.py renamed to veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py

File renamed without changes.

veadk/integrations/ve_faas/template/config.yaml.example renamed to veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example

File renamed without changes.

veadk/integrations/ve_faas/template/deploy.py renamed to veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@
2424
SESSION_ID = "cloud_app_test_session"
2525
USER_ID = "cloud_app_test_user"
2626

27-
VEFAAS_APPLICATION_NAME = "weather-reporter"
28-
GATEWAY_NAME = ""
29-
GATEWAY_SERVICE_NAME = ""
30-
GATEWAY_UPSTREAMNAME = ""
31-
USE_ADK_WEB = False
32-
3327

3428
async def _send_msg_with_a2a(cloud_app: CloudApp, message: str) -> None:
3529
print("===== A2A example =====")
@@ -85,16 +79,16 @@ async def main():
8579

8680
cloud_app = engine.deploy(
8781
path=str(Path(__file__).parent / "src"),
88-
application_name=VEFAAS_APPLICATION_NAME,
89-
gateway_name=GATEWAY_NAME,
90-
gateway_service_name=GATEWAY_SERVICE_NAME,
91-
gateway_upstream_name=GATEWAY_UPSTREAMNAME,
92-
use_adk_web=USE_ADK_WEB,
82+
application_name="{{cookiecutter.vefaas_application_name}}",
83+
gateway_name="{{cookiecutter.veapig_instance_name}}",
84+
gateway_service_name="{{cookiecutter.veapig_service_name}}",
85+
gateway_upstream_name="{{cookiecutter.veapig_upstream_name}}",
86+
use_adk_web={{cookiecutter.use_adk_web}},
9387
local_test=False, # Set to True for local testing before deploy to VeFaaS
9488
)
9589
print(f"VeFaaS application ID: {cloud_app.vefaas_application_id}")
9690

97-
if USE_ADK_WEB:
91+
if {{cookiecutter.use_adk_web}}:
9892
print(f"Web is running at: {cloud_app.vefaas_endpoint}")
9993
else:
10094
# Test with deployed cloud application

0 commit comments

Comments
 (0)