veadk-python 0.2.27__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. veadk/__init__.py +37 -0
  2. veadk/a2a/__init__.py +13 -0
  3. veadk/a2a/agent_card.py +45 -0
  4. veadk/a2a/remote_ve_agent.py +390 -0
  5. veadk/a2a/utils/__init__.py +13 -0
  6. veadk/a2a/utils/agent_to_a2a.py +170 -0
  7. veadk/a2a/ve_a2a_server.py +93 -0
  8. veadk/a2a/ve_agent_executor.py +78 -0
  9. veadk/a2a/ve_middlewares.py +313 -0
  10. veadk/a2a/ve_task_store.py +37 -0
  11. veadk/agent.py +402 -0
  12. veadk/agent_builder.py +93 -0
  13. veadk/agents/loop_agent.py +68 -0
  14. veadk/agents/parallel_agent.py +72 -0
  15. veadk/agents/sequential_agent.py +64 -0
  16. veadk/auth/__init__.py +13 -0
  17. veadk/auth/base_auth.py +22 -0
  18. veadk/auth/ve_credential_service.py +203 -0
  19. veadk/auth/veauth/__init__.py +13 -0
  20. veadk/auth/veauth/apmplus_veauth.py +58 -0
  21. veadk/auth/veauth/ark_veauth.py +75 -0
  22. veadk/auth/veauth/base_veauth.py +50 -0
  23. veadk/auth/veauth/cozeloop_veauth.py +13 -0
  24. veadk/auth/veauth/opensearch_veauth.py +75 -0
  25. veadk/auth/veauth/postgresql_veauth.py +75 -0
  26. veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
  27. veadk/auth/veauth/speech_veauth.py +54 -0
  28. veadk/auth/veauth/utils.py +69 -0
  29. veadk/auth/veauth/vesearch_veauth.py +62 -0
  30. veadk/auth/veauth/viking_mem0_veauth.py +91 -0
  31. veadk/cli/__init__.py +13 -0
  32. veadk/cli/cli.py +58 -0
  33. veadk/cli/cli_clean.py +87 -0
  34. veadk/cli/cli_create.py +163 -0
  35. veadk/cli/cli_deploy.py +233 -0
  36. veadk/cli/cli_eval.py +215 -0
  37. veadk/cli/cli_init.py +214 -0
  38. veadk/cli/cli_kb.py +110 -0
  39. veadk/cli/cli_pipeline.py +285 -0
  40. veadk/cli/cli_prompt.py +86 -0
  41. veadk/cli/cli_update.py +106 -0
  42. veadk/cli/cli_uploadevalset.py +139 -0
  43. veadk/cli/cli_web.py +143 -0
  44. veadk/cloud/__init__.py +13 -0
  45. veadk/cloud/cloud_agent_engine.py +485 -0
  46. veadk/cloud/cloud_app.py +475 -0
  47. veadk/config.py +115 -0
  48. veadk/configs/__init__.py +13 -0
  49. veadk/configs/auth_configs.py +133 -0
  50. veadk/configs/database_configs.py +132 -0
  51. veadk/configs/model_configs.py +78 -0
  52. veadk/configs/tool_configs.py +54 -0
  53. veadk/configs/tracing_configs.py +110 -0
  54. veadk/consts.py +74 -0
  55. veadk/evaluation/__init__.py +17 -0
  56. veadk/evaluation/adk_evaluator/__init__.py +17 -0
  57. veadk/evaluation/adk_evaluator/adk_evaluator.py +302 -0
  58. veadk/evaluation/base_evaluator.py +642 -0
  59. veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
  60. veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +339 -0
  61. veadk/evaluation/eval_set_file_loader.py +48 -0
  62. veadk/evaluation/eval_set_recorder.py +146 -0
  63. veadk/evaluation/types.py +65 -0
  64. veadk/evaluation/utils/prometheus.py +196 -0
  65. veadk/integrations/__init__.py +13 -0
  66. veadk/integrations/ve_apig/__init__.py +13 -0
  67. veadk/integrations/ve_apig/ve_apig.py +349 -0
  68. veadk/integrations/ve_apig/ve_apig_utils.py +332 -0
  69. veadk/integrations/ve_code_pipeline/__init__.py +13 -0
  70. veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
  71. veadk/integrations/ve_cozeloop/__init__.py +13 -0
  72. veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
  73. veadk/integrations/ve_cr/__init__.py +13 -0
  74. veadk/integrations/ve_cr/ve_cr.py +220 -0
  75. veadk/integrations/ve_faas/__init__.py +13 -0
  76. veadk/integrations/ve_faas/template/cookiecutter.json +15 -0
  77. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  78. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  79. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example +6 -0
  80. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +106 -0
  81. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__init__.py +13 -0
  82. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +25 -0
  83. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +202 -0
  84. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -0
  85. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +49 -0
  86. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/__init__.py +14 -0
  87. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/agent.py +27 -0
  88. veadk/integrations/ve_faas/ve_faas.py +754 -0
  89. veadk/integrations/ve_faas/ve_faas_utils.py +408 -0
  90. veadk/integrations/ve_faas/web_template/cookiecutter.json +20 -0
  91. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  92. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  93. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
  94. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +44 -0
  95. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
  96. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
  97. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
  98. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
  99. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
  100. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
  101. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
  102. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
  103. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
  104. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
  105. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
  106. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
  107. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
  108. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
  109. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
  110. veadk/integrations/ve_identity/__init__.py +110 -0
  111. veadk/integrations/ve_identity/auth_config.py +261 -0
  112. veadk/integrations/ve_identity/auth_mixins.py +650 -0
  113. veadk/integrations/ve_identity/auth_processor.py +385 -0
  114. veadk/integrations/ve_identity/function_tool.py +158 -0
  115. veadk/integrations/ve_identity/identity_client.py +864 -0
  116. veadk/integrations/ve_identity/mcp_tool.py +181 -0
  117. veadk/integrations/ve_identity/mcp_toolset.py +431 -0
  118. veadk/integrations/ve_identity/models.py +228 -0
  119. veadk/integrations/ve_identity/token_manager.py +188 -0
  120. veadk/integrations/ve_identity/utils.py +151 -0
  121. veadk/integrations/ve_prompt_pilot/__init__.py +13 -0
  122. veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +85 -0
  123. veadk/integrations/ve_tls/__init__.py +13 -0
  124. veadk/integrations/ve_tls/utils.py +116 -0
  125. veadk/integrations/ve_tls/ve_tls.py +212 -0
  126. veadk/integrations/ve_tos/ve_tos.py +710 -0
  127. veadk/integrations/ve_viking_db_memory/__init__.py +13 -0
  128. veadk/integrations/ve_viking_db_memory/ve_viking_db_memory.py +308 -0
  129. veadk/knowledgebase/__init__.py +17 -0
  130. veadk/knowledgebase/backends/__init__.py +13 -0
  131. veadk/knowledgebase/backends/base_backend.py +72 -0
  132. veadk/knowledgebase/backends/in_memory_backend.py +91 -0
  133. veadk/knowledgebase/backends/opensearch_backend.py +162 -0
  134. veadk/knowledgebase/backends/redis_backend.py +172 -0
  135. veadk/knowledgebase/backends/utils.py +92 -0
  136. veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +608 -0
  137. veadk/knowledgebase/entry.py +25 -0
  138. veadk/knowledgebase/knowledgebase.py +307 -0
  139. veadk/memory/__init__.py +35 -0
  140. veadk/memory/long_term_memory.py +365 -0
  141. veadk/memory/long_term_memory_backends/__init__.py +13 -0
  142. veadk/memory/long_term_memory_backends/base_backend.py +35 -0
  143. veadk/memory/long_term_memory_backends/in_memory_backend.py +67 -0
  144. veadk/memory/long_term_memory_backends/mem0_backend.py +155 -0
  145. veadk/memory/long_term_memory_backends/opensearch_backend.py +124 -0
  146. veadk/memory/long_term_memory_backends/redis_backend.py +140 -0
  147. veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +189 -0
  148. veadk/memory/short_term_memory.py +252 -0
  149. veadk/memory/short_term_memory_backends/__init__.py +13 -0
  150. veadk/memory/short_term_memory_backends/base_backend.py +31 -0
  151. veadk/memory/short_term_memory_backends/mysql_backend.py +49 -0
  152. veadk/memory/short_term_memory_backends/postgresql_backend.py +49 -0
  153. veadk/memory/short_term_memory_backends/sqlite_backend.py +55 -0
  154. veadk/memory/short_term_memory_processor.py +100 -0
  155. veadk/processors/__init__.py +26 -0
  156. veadk/processors/base_run_processor.py +120 -0
  157. veadk/prompts/__init__.py +13 -0
  158. veadk/prompts/agent_default_prompt.py +30 -0
  159. veadk/prompts/prompt_evaluator.py +20 -0
  160. veadk/prompts/prompt_memory_processor.py +55 -0
  161. veadk/prompts/prompt_optimization.py +150 -0
  162. veadk/runner.py +732 -0
  163. veadk/tools/__init__.py +13 -0
  164. veadk/tools/builtin_tools/__init__.py +13 -0
  165. veadk/tools/builtin_tools/agent_authorization.py +94 -0
  166. veadk/tools/builtin_tools/generate_image.py +23 -0
  167. veadk/tools/builtin_tools/image_edit.py +300 -0
  168. veadk/tools/builtin_tools/image_generate.py +446 -0
  169. veadk/tools/builtin_tools/lark.py +67 -0
  170. veadk/tools/builtin_tools/las.py +24 -0
  171. veadk/tools/builtin_tools/link_reader.py +66 -0
  172. veadk/tools/builtin_tools/llm_shield.py +381 -0
  173. veadk/tools/builtin_tools/load_knowledgebase.py +97 -0
  174. veadk/tools/builtin_tools/mcp_router.py +29 -0
  175. veadk/tools/builtin_tools/run_code.py +113 -0
  176. veadk/tools/builtin_tools/tts.py +253 -0
  177. veadk/tools/builtin_tools/vesearch.py +49 -0
  178. veadk/tools/builtin_tools/video_generate.py +363 -0
  179. veadk/tools/builtin_tools/web_scraper.py +76 -0
  180. veadk/tools/builtin_tools/web_search.py +83 -0
  181. veadk/tools/demo_tools.py +58 -0
  182. veadk/tools/load_knowledgebase_tool.py +149 -0
  183. veadk/tools/sandbox/__init__.py +13 -0
  184. veadk/tools/sandbox/browser_sandbox.py +37 -0
  185. veadk/tools/sandbox/code_sandbox.py +40 -0
  186. veadk/tools/sandbox/computer_sandbox.py +34 -0
  187. veadk/tracing/__init__.py +13 -0
  188. veadk/tracing/base_tracer.py +58 -0
  189. veadk/tracing/telemetry/__init__.py +13 -0
  190. veadk/tracing/telemetry/attributes/attributes.py +29 -0
  191. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +180 -0
  192. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +858 -0
  193. veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +152 -0
  194. veadk/tracing/telemetry/attributes/extractors/types.py +164 -0
  195. veadk/tracing/telemetry/exporters/__init__.py +13 -0
  196. veadk/tracing/telemetry/exporters/apmplus_exporter.py +558 -0
  197. veadk/tracing/telemetry/exporters/base_exporter.py +39 -0
  198. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +129 -0
  199. veadk/tracing/telemetry/exporters/inmemory_exporter.py +248 -0
  200. veadk/tracing/telemetry/exporters/tls_exporter.py +139 -0
  201. veadk/tracing/telemetry/opentelemetry_tracer.py +320 -0
  202. veadk/tracing/telemetry/telemetry.py +411 -0
  203. veadk/types.py +47 -0
  204. veadk/utils/__init__.py +13 -0
  205. veadk/utils/audio_manager.py +95 -0
  206. veadk/utils/auth.py +294 -0
  207. veadk/utils/logger.py +59 -0
  208. veadk/utils/mcp_utils.py +44 -0
  209. veadk/utils/misc.py +184 -0
  210. veadk/utils/patches.py +101 -0
  211. veadk/utils/volcengine_sign.py +205 -0
  212. veadk/version.py +15 -0
  213. veadk_python-0.2.27.dist-info/METADATA +373 -0
  214. veadk_python-0.2.27.dist-info/RECORD +218 -0
  215. veadk_python-0.2.27.dist-info/WHEEL +5 -0
  216. veadk_python-0.2.27.dist-info/entry_points.txt +2 -0
  217. veadk_python-0.2.27.dist-info/licenses/LICENSE +201 -0
  218. veadk_python-0.2.27.dist-info/top_level.txt +1 -0
@@ -0,0 +1,408 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # This file is partly adapted from https://github.com/volcengine/mcp-server/blob/main/server/mcp_server_vefaas_function/src/mcp_server_vefaas_function/vefaas_server.py
16
+
17
+ import base64
18
+ import datetime
19
+ import hashlib
20
+ import hmac
21
+ import json
22
+ import os
23
+ import shutil
24
+ import subprocess
25
+ import zipfile
26
+ from io import BytesIO
27
+ from pathlib import Path
28
+ from typing import Tuple
29
+ from urllib.parse import quote
30
+
31
+ import requests
32
+ from volcenginesdkcore.rest import ApiException
33
+
34
+ Service = "apig"
35
+ Version = "2021-03-03"
36
+ Region = "cn-beijing"
37
+ Host = "iam.volcengineapi.com"
38
+ ContentType = "application/x-www-form-urlencoded"
39
+
40
+
41
+ def ensure_executable_permissions(folder_path: str):
42
+ for root, _, files in os.walk(folder_path):
43
+ for fname in files:
44
+ full_path = os.path.join(root, fname)
45
+ if fname.endswith(".sh") or fname in ("run.sh",):
46
+ os.chmod(full_path, 0o755)
47
+
48
+
49
+ def python_zip_implementation(folder_path: str) -> bytes:
50
+ """Pure Python zip implementation with permissions support"""
51
+ buffer = BytesIO()
52
+
53
+ with zipfile.ZipFile(buffer, "w", compression=zipfile.ZIP_DEFLATED) as zipf:
54
+ for root, dirs, files in os.walk(folder_path):
55
+ for file in files:
56
+ file_path = os.path.join(root, file)
57
+ arcname = os.path.relpath(file_path, folder_path)
58
+
59
+ # Skip excluded paths and binary/cache files
60
+ if any(
61
+ excl in arcname for excl in [".git", ".venv", "__pycache__", ".pyc"]
62
+ ):
63
+ continue
64
+
65
+ try:
66
+ st = os.stat(file_path)
67
+ dt = datetime.datetime.fromtimestamp(st.st_mtime)
68
+ date_time = (
69
+ dt.year,
70
+ dt.month,
71
+ dt.day,
72
+ dt.hour,
73
+ dt.minute,
74
+ dt.second,
75
+ )
76
+
77
+ info = zipfile.ZipInfo(arcname)
78
+ info.external_attr = 0o755 << 16 # rwxr-xr-x
79
+ info.date_time = date_time
80
+
81
+ with open(file_path, "rb") as f:
82
+ zipf.writestr(info, f.read())
83
+ except Exception as e:
84
+ print(f"Warning: Skipping file {arcname} due to error: {str(e)}")
85
+
86
+ print(f"Your .zip project size: {buffer.tell() / 1024 / 1024:.2f} MB")
87
+ return buffer.getvalue()
88
+
89
+
90
+ def zip_and_encode_folder(folder_path: str) -> Tuple[bytes, int, Exception]:
91
+ """
92
+ Zips a folder with system zip command (if available) or falls back to Python implementation.
93
+ Returns (zip_data, size_in_bytes, error) tuple.
94
+ """
95
+ # Check for system zip first
96
+ if not shutil.which("zip"):
97
+ print("System zip command not found, using Python implementation")
98
+ try:
99
+ data = python_zip_implementation(folder_path)
100
+ return data, len(data), None
101
+ except Exception as e:
102
+ return None, 0, e
103
+
104
+ # print(f"Zipping folder: {folder_path}")
105
+ try:
106
+ ensure_executable_permissions(folder_path)
107
+ # Create zip process with explicit arguments
108
+ proc = subprocess.Popen(
109
+ [
110
+ "zip",
111
+ "-r",
112
+ "-q",
113
+ "-",
114
+ ".",
115
+ "-x",
116
+ "*.git*",
117
+ "-x",
118
+ "*.venv*",
119
+ "-x",
120
+ "*__pycache__*",
121
+ "-x",
122
+ "*.pyc",
123
+ ],
124
+ cwd=folder_path,
125
+ stdout=subprocess.PIPE,
126
+ stderr=subprocess.PIPE,
127
+ bufsize=1024 * 8, # 8KB buffer
128
+ )
129
+
130
+ # Collect output with proper error handling
131
+ try:
132
+ stdout, stderr = proc.communicate(timeout=30)
133
+ if proc.returncode != 0:
134
+ print(f"Zip error: {stderr.decode()}")
135
+ data = python_zip_implementation(folder_path)
136
+ return data, len(data), None
137
+
138
+ if stdout:
139
+ size = len(stdout)
140
+ # print(f"Zip finished, size: {size / 1024 / 1024:.2f} MB")
141
+ return stdout, size, None
142
+ else:
143
+ print("No data from zip command, falling back to Python implementation")
144
+ data = python_zip_implementation(folder_path)
145
+ return data, len(data), None
146
+
147
+ except subprocess.TimeoutExpired:
148
+ proc.kill()
149
+ proc.wait(timeout=5) # Give it 5 seconds to cleanup
150
+ print("Zip process timed out, falling back to Python implementation")
151
+ try:
152
+ data = python_zip_implementation(folder_path)
153
+ return data, len(data), None
154
+ except Exception as e:
155
+ return None, 0, e
156
+
157
+ except Exception as e:
158
+ print(f"System zip error: {str(e)}")
159
+ try:
160
+ data = python_zip_implementation(folder_path)
161
+ return data, len(data), None
162
+ except Exception as e2:
163
+ return None, 0, e2
164
+
165
+
166
+ def get_project_path() -> str:
167
+ """Pack the whole project into a zip file."""
168
+ proj_dir = Path(__file__).parent.parent.parent
169
+ return proj_dir
170
+
171
+
172
+ def encoding():
173
+ with open("/root/test_data/test_zip.zip", "rb") as zip_file:
174
+ zip_binary = zip_file.read()
175
+ zip_base64 = base64.b64encode(zip_binary).decode("utf-8")
176
+ return zip_base64
177
+
178
+
179
+ def hmac_sha256(key: bytes, content: str):
180
+ return hmac.new(key, content.encode("utf-8"), hashlib.sha256).digest()
181
+
182
+
183
+ def hash_sha256(content: str):
184
+ return hashlib.sha256(content.encode("utf-8")).hexdigest()
185
+
186
+
187
+ def norm_query(params):
188
+ query = ""
189
+ for key in sorted(params.keys()):
190
+ if isinstance(params[key], list):
191
+ for k in params[key]:
192
+ query = (
193
+ query + quote(key, safe="-_.~") + "=" + quote(k, safe="-_.~") + "&"
194
+ )
195
+ else:
196
+ query = (
197
+ query
198
+ + quote(key, safe="-_.~")
199
+ + "="
200
+ + quote(params[key], safe="-_.~")
201
+ + "&"
202
+ )
203
+ query = query[:-1]
204
+ return query.replace("+", "%20")
205
+
206
+
207
+ def request(method, date, query, header, ak, sk, token, action, body):
208
+ credential = {
209
+ "access_key_id": ak,
210
+ "secret_access_key": sk,
211
+ "service": Service,
212
+ "region": Region,
213
+ }
214
+
215
+ if token is not None:
216
+ credential["session_token"] = token
217
+
218
+ if action in [
219
+ "CodeUploadCallback",
220
+ "CreateDependencyInstallTask",
221
+ "GetReleaseStatus",
222
+ "GetDependencyInstallTaskStatus",
223
+ ]:
224
+ credential["service"] = "vefaas"
225
+
226
+ content_type = ContentType
227
+ version = Version
228
+ if method == "POST":
229
+ content_type = "application/json"
230
+
231
+ if action == "CreateRoute" or action == "ListRoutes":
232
+ version = "2022-11-12"
233
+
234
+ request_param = {
235
+ "body": body,
236
+ "host": Host,
237
+ "path": "/",
238
+ "method": method,
239
+ "content_type": content_type,
240
+ "date": date,
241
+ "query": {"Action": action, "Version": version, **query},
242
+ }
243
+ if body is None:
244
+ request_param["body"] = ""
245
+
246
+ x_date = request_param["date"].strftime("%Y%m%dT%H%M%SZ")
247
+ short_x_date = x_date[:8]
248
+ x_content_sha256 = hash_sha256(request_param["body"])
249
+ sign_result = {
250
+ "Host": request_param["host"],
251
+ "X-Content-Sha256": x_content_sha256,
252
+ "X-Date": x_date,
253
+ "Content-Type": request_param["content_type"],
254
+ }
255
+
256
+ signed_headers_str = ";".join(
257
+ ["content-type", "host", "x-content-sha256", "x-date"]
258
+ )
259
+ # signed_headers_str = signed_headers_str + ";x-security-token"
260
+ canonical_request_str = "\n".join(
261
+ [
262
+ request_param["method"].upper(),
263
+ request_param["path"],
264
+ norm_query(request_param["query"]),
265
+ "\n".join(
266
+ [
267
+ "content-type:" + request_param["content_type"],
268
+ "host:" + request_param["host"],
269
+ "x-content-sha256:" + x_content_sha256,
270
+ "x-date:" + x_date,
271
+ ]
272
+ ),
273
+ "",
274
+ signed_headers_str,
275
+ x_content_sha256,
276
+ ]
277
+ )
278
+
279
+ hashed_canonical_request = hash_sha256(canonical_request_str)
280
+
281
+ credential_scope = "/".join(
282
+ [short_x_date, credential["region"], credential["service"], "request"]
283
+ )
284
+ string_to_sign = "\n".join(
285
+ ["HMAC-SHA256", x_date, credential_scope, hashed_canonical_request]
286
+ )
287
+
288
+ k_date = hmac_sha256(credential["secret_access_key"].encode("utf-8"), short_x_date)
289
+ k_region = hmac_sha256(k_date, credential["region"])
290
+ k_service = hmac_sha256(k_region, credential["service"])
291
+ k_signing = hmac_sha256(k_service, "request")
292
+ signature = hmac_sha256(k_signing, string_to_sign).hex()
293
+
294
+ sign_result["Authorization"] = (
295
+ "HMAC-SHA256 Credential={}, SignedHeaders={}, Signature={}".format(
296
+ credential["access_key_id"] + "/" + credential_scope,
297
+ signed_headers_str,
298
+ signature,
299
+ )
300
+ )
301
+ header = {**header, **sign_result}
302
+ header = {**header, **{"X-Security-Token": token}}
303
+ r = requests.request(
304
+ method=method,
305
+ url="https://{}{}".format(request_param["host"], request_param["path"]),
306
+ headers=header,
307
+ params=request_param["query"],
308
+ data=request_param["body"],
309
+ )
310
+ return r.json()
311
+
312
+
313
+ def signed_request(ak: str, sk: str, target: str, body: dict):
314
+ now = datetime.datetime.utcnow()
315
+
316
+ try:
317
+ response_body = request(
318
+ "POST",
319
+ now,
320
+ {},
321
+ {},
322
+ ak,
323
+ sk,
324
+ "",
325
+ target,
326
+ json.dumps(body),
327
+ )
328
+ return response_body
329
+ except Exception as e:
330
+ error_message = f"Error creating upstream: {str(e)}"
331
+ raise ValueError(error_message)
332
+ except ApiException as e:
333
+ print("Exception when calling API: %s\n" % e)
334
+
335
+
336
+ def create_api_gateway_trigger(
337
+ ak, sk, function_id: str, api_gateway_id: str, service_id: str, region: str = None
338
+ ):
339
+ token = ""
340
+
341
+ now = datetime.datetime.utcnow()
342
+
343
+ body = {
344
+ "Name": f"{function_id}-trigger",
345
+ "GatewayId": api_gateway_id,
346
+ "SourceType": "VeFaas",
347
+ "UpstreamSpec": {"VeFaas": {"FunctionId": function_id}},
348
+ }
349
+
350
+ try:
351
+ response_body = request(
352
+ "POST", now, {}, {}, ak, sk, token, "CreateUpstream", json.dumps(body)
353
+ )
354
+ # Print the full response for debugging
355
+ # print(f"Response: {json.dumps(response_body)}")
356
+ # Check if response contains an error
357
+ if "Error" in response_body or (
358
+ "ResponseMetadata" in response_body
359
+ and "Error" in response_body["ResponseMetadata"]
360
+ ):
361
+ error_info = response_body.get("Error") or response_body[
362
+ "ResponseMetadata"
363
+ ].get("Error")
364
+ error_message = f"API Error: {error_info.get('Message', 'Unknown error')}"
365
+ raise ValueError(error_message)
366
+
367
+ # Check if Result exists in the response
368
+ if "Result" not in response_body:
369
+ raise ValueError(f"API call did not return a Result field: {response_body}")
370
+
371
+ upstream_id = response_body["Result"]["Id"]
372
+ except Exception as e:
373
+ error_message = f"Error creating upstream: {str(e)}"
374
+ raise ValueError(error_message)
375
+
376
+ body = {
377
+ "Name": "router1",
378
+ "UpstreamList": [{"Type": "VeFaas", "UpstreamId": upstream_id, "Weight": 100}],
379
+ "ServiceId": service_id,
380
+ "MatchRule": {
381
+ "Method": ["POST", "GET", "PUT", "DELETE", "HEAD", "OPTIONS"],
382
+ "Path": {"MatchType": "Prefix", "MatchContent": "/"},
383
+ },
384
+ "AdvancedSetting": {
385
+ "TimeoutSetting": {"Enable": False, "Timeout": 30},
386
+ "CorsPolicySetting": {"Enable": False},
387
+ },
388
+ }
389
+ try:
390
+ response_body = request(
391
+ "POST", now, {}, {}, ak, sk, token, "CreateRoute", json.dumps(body)
392
+ )
393
+ except Exception as e:
394
+ error_message = f"Error creating route: {str(e)}"
395
+ raise ValueError(error_message)
396
+ return response_body
397
+
398
+
399
+ def list_routes(ak, sk, upstream_id: str):
400
+ now = datetime.datetime.utcnow()
401
+ token = ""
402
+
403
+ body = {"UpstreamId": upstream_id}
404
+
405
+ response_body = request(
406
+ "POST", now, {}, {}, ak, sk, token, "ListRoutes", json.dumps(body)
407
+ )
408
+ return response_body
@@ -0,0 +1,20 @@
1
+ {
2
+ "local_dir_name": "veadk_vefaas_web_proj",
3
+ "app_name": "simple-blog",
4
+ "vefaas_application_name": "simple-blog",
5
+ "veapig_instance_name": "",
6
+ "veapig_service_name": "",
7
+ "veapig_upstream_name": "",
8
+ "use_adk_web": false,
9
+ "auth_method": "none",
10
+ "veidentity_user_pool_name": "",
11
+ "veidentity_client_name": "",
12
+ "veadk_version": "",
13
+ "_copy_without_render": [
14
+ "*.html",
15
+ "*.css",
16
+ "*.js",
17
+ "static/**/*",
18
+ "templates/**/*"
19
+ ]
20
+ }
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from veadk.cloud.cloud_app import CloudApp
16
+
17
+ def main() -> None:
18
+ cloud_app = CloudApp(vefaas_application_name="{{cookiecutter.vefaas_application_name}}")
19
+ cloud_app.delete_self()
20
+
21
+
22
+ if __name__ == "__main__":
23
+ main()
@@ -0,0 +1,2 @@
1
+ VOLCENGINE_ACCESS_KEY:
2
+ VOLCENGINE_SECRET_KEY:
@@ -0,0 +1,44 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import asyncio
16
+ from pathlib import Path
17
+
18
+ from veadk.cloud.cloud_agent_engine import CloudAgentEngine
19
+
20
+ async def main():
21
+ engine = CloudAgentEngine()
22
+
23
+ cloud_app = engine.deploy(
24
+ path=str(Path(__file__).parent / "src"),
25
+ application_name="{{cookiecutter.vefaas_application_name}}",
26
+ gateway_name="{{cookiecutter.veapig_instance_name}}",
27
+ gateway_service_name="{{cookiecutter.veapig_service_name}}",
28
+ gateway_upstream_name="{{cookiecutter.veapig_upstream_name}}",
29
+ use_adk_web={{cookiecutter.use_adk_web}},
30
+ auth_method="{{cookiecutter.auth_method}}",
31
+ identity_user_pool_name="{{cookiecutter.veidentity_user_pool_name}}",
32
+ identity_client_name="{{cookiecutter.veidentity_client_name}}",
33
+ local_test=False, # Set to True for local testing before deploy to VeFaaS
34
+ )
35
+ print(f"VeFaaS application ID: {cloud_app.vefaas_application_id}")
36
+
37
+ if {{cookiecutter.use_adk_web}}:
38
+ print(f"Web is running at: {cloud_app.vefaas_endpoint}")
39
+ else:
40
+ print(f"Web template does not support use_adk_web=False")
41
+
42
+
43
+ if __name__ == "__main__":
44
+ asyncio.run(main())
@@ -0,0 +1,23 @@
1
+ # 使用官方Python镜像作为基础镜像
2
+ FROM python:3.9-slim
3
+
4
+ # 设置工作目录
5
+ WORKDIR /app
6
+
7
+ # 复制依赖文件并安装依赖
8
+ COPY requirements.txt .
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ # 复制项目文件
12
+ COPY . .
13
+
14
+ # 设置环境变量
15
+ ENV FLASK_APP=app.py
16
+ ENV FLASK_ENV=production
17
+ ENV PYTHONUNBUFFERED=1
18
+
19
+ # 暴露端口
20
+ EXPOSE 8000
21
+
22
+ # 启动命令
23
+ CMD ["bash", "run.sh"]
@@ -0,0 +1,123 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from flask import Flask, render_template, request, redirect, url_for, flash, session
16
+ from models import db, Post, User
17
+ from werkzeug.security import generate_password_hash, check_password_hash
18
+ import os
19
+
20
+ app = Flask(__name__)
21
+ app.config['SECRET_KEY'] = 'your-secret-key-here'
22
+ app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
23
+ app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
24
+ app.instance_path = os.path.join("/tmp", "flask_instance")
25
+ os.makedirs(app.instance_path, exist_ok=True)
26
+
27
+ db.init_app(app)
28
+
29
+ # 前台首页
30
+ @app.route('/')
31
+ def index():
32
+ page = request.args.get('page', 1, type=int)
33
+ posts = Post.query.order_by(Post.created_at.desc()).paginate(
34
+ page=page, per_page=5, error_out=False)
35
+ return render_template('index.html', posts=posts)
36
+
37
+ # 文章详情页
38
+ @app.route('/post/<int:post_id>')
39
+ def post_detail(post_id):
40
+ post = Post.query.get_or_404(post_id)
41
+ return render_template('post.html', post=post)
42
+
43
+ # 后台登录页
44
+ @app.route('/admin/login', methods=['GET', 'POST'])
45
+ def admin_login():
46
+ if request.method == 'POST':
47
+ username = request.form['username']
48
+ password = request.form['password']
49
+
50
+ user = User.query.filter_by(username=username).first()
51
+
52
+ if user and check_password_hash(user.password, password):
53
+ session['admin_logged_in'] = True
54
+ return redirect(url_for('admin_dashboard'))
55
+ else:
56
+ flash('用户名或密码错误')
57
+
58
+ return render_template('admin/login.html')
59
+
60
+ # 后台登出
61
+ @app.route('/admin/logout')
62
+ def admin_logout():
63
+ session.pop('admin_logged_in', None)
64
+ return redirect(url_for('admin_login'))
65
+
66
+ # 后台管理面板
67
+ @app.route('/admin/dashboard')
68
+ def admin_dashboard():
69
+ if not session.get('admin_logged_in'):
70
+ return redirect(url_for('admin_login'))
71
+
72
+ post_count = Post.query.count()
73
+ return render_template('admin/dashboard.html', post_count=post_count)
74
+
75
+ # 文章管理
76
+ @app.route('/admin/posts')
77
+ def admin_posts():
78
+ if not session.get('admin_logged_in'):
79
+ return redirect(url_for('admin_login'))
80
+
81
+ page = request.args.get('page', 1, type=int)
82
+ posts = Post.query.order_by(Post.created_at.desc()).paginate(
83
+ page=page, per_page=10, error_out=False)
84
+ return render_template('admin/posts.html', posts=posts)
85
+
86
+ # 创建/编辑文章
87
+ @app.route('/admin/post', methods=['GET', 'POST'])
88
+ @app.route('/admin/post/<int:post_id>', methods=['GET', 'POST'])
89
+ def admin_edit_post(post_id=None):
90
+ if not session.get('admin_logged_in'):
91
+ return redirect(url_for('admin_login'))
92
+
93
+ if post_id:
94
+ post = Post.query.get_or_404(post_id)
95
+ else:
96
+ post = Post()
97
+
98
+ if request.method == 'POST':
99
+ post.title = request.form['title']
100
+ post.content = request.form['content']
101
+
102
+ if post_id is None:
103
+ db.session.add(post)
104
+ db.session.commit()
105
+ flash('文章保存成功')
106
+ return redirect(url_for('admin_posts'))
107
+
108
+ return render_template('admin/edit_post.html', post=post)
109
+
110
+ # 删除文章
111
+ @app.route('/admin/post/delete/<int:post_id>', methods=['POST'])
112
+ def admin_delete_post(post_id):
113
+ if not session.get('admin_logged_in'):
114
+ return redirect(url_for('admin_login'))
115
+
116
+ post = Post.query.get_or_404(post_id)
117
+ db.session.delete(post)
118
+ db.session.commit()
119
+ flash('文章删除成功')
120
+ return redirect(url_for('admin_posts'))
121
+
122
+ if __name__ == '__main__':
123
+ app.run(debug=True)