veadk-python 0.2.5__py3-none-any.whl → 0.2.7__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.

Potentially problematic release.


This version of veadk-python might be problematic. Click here for more details.

Files changed (94) hide show
  1. veadk/agent.py +29 -22
  2. veadk/agent_builder.py +94 -0
  3. veadk/auth/__init__.py +13 -0
  4. veadk/auth/base_auth.py +22 -0
  5. veadk/auth/veauth/__init__.py +13 -0
  6. veadk/auth/veauth/apmplus_veauth.py +65 -0
  7. veadk/auth/veauth/ark_veauth.py +77 -0
  8. veadk/auth/veauth/base_veauth.py +50 -0
  9. veadk/auth/veauth/cozeloop_veauth.py +13 -0
  10. veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
  11. veadk/auth/veauth/vesearch_veauth.py +62 -0
  12. veadk/cli/cli.py +2 -0
  13. veadk/cli/cli_deploy.py +5 -2
  14. veadk/cli/cli_init.py +25 -6
  15. veadk/cli/cli_pipeline.py +220 -0
  16. veadk/cli/cli_prompt.py +4 -4
  17. veadk/config.py +45 -81
  18. veadk/configs/__init__.py +13 -0
  19. veadk/configs/database_configs.py +83 -0
  20. veadk/configs/model_configs.py +42 -0
  21. veadk/configs/tool_configs.py +42 -0
  22. veadk/configs/tracing_configs.py +110 -0
  23. veadk/consts.py +32 -1
  24. veadk/database/database_adapter.py +256 -3
  25. veadk/database/kv/redis_database.py +47 -0
  26. veadk/database/local_database.py +23 -4
  27. veadk/database/relational/mysql_database.py +58 -0
  28. veadk/database/vector/opensearch_vector_database.py +6 -3
  29. veadk/database/viking/viking_database.py +272 -36
  30. veadk/integrations/ve_code_pipeline/__init__.py +13 -0
  31. veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
  32. veadk/integrations/ve_cozeloop/__init__.py +13 -0
  33. veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
  34. veadk/integrations/ve_cr/__init__.py +13 -0
  35. veadk/integrations/ve_cr/ve_cr.py +220 -0
  36. veadk/integrations/ve_faas/template/cookiecutter.json +3 -2
  37. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +2 -2
  38. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +1 -1
  39. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +24 -1
  40. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -1
  41. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +1 -12
  42. veadk/integrations/ve_faas/ve_faas.py +352 -35
  43. veadk/integrations/ve_faas/web_template/cookiecutter.json +17 -0
  44. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  45. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  46. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
  47. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +41 -0
  48. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
  49. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
  50. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
  51. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
  52. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
  53. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
  54. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
  55. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
  56. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
  57. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
  58. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
  59. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
  60. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
  61. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
  62. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
  63. veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +6 -3
  64. veadk/integrations/ve_tls/__init__.py +13 -0
  65. veadk/integrations/ve_tls/utils.py +117 -0
  66. veadk/integrations/ve_tls/ve_tls.py +208 -0
  67. veadk/integrations/ve_tos/ve_tos.py +128 -73
  68. veadk/knowledgebase/knowledgebase.py +116 -20
  69. veadk/memory/long_term_memory.py +20 -21
  70. veadk/memory/short_term_memory_processor.py +9 -4
  71. veadk/runner.py +213 -223
  72. veadk/tools/builtin_tools/vesearch.py +2 -2
  73. veadk/tools/builtin_tools/video_generate.py +27 -20
  74. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +5 -0
  75. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +253 -129
  76. veadk/tracing/telemetry/attributes/extractors/types.py +15 -4
  77. veadk/tracing/telemetry/exporters/apmplus_exporter.py +158 -12
  78. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +4 -9
  79. veadk/tracing/telemetry/exporters/tls_exporter.py +4 -10
  80. veadk/tracing/telemetry/opentelemetry_tracer.py +11 -5
  81. veadk/tracing/telemetry/telemetry.py +23 -5
  82. veadk/utils/logger.py +1 -1
  83. veadk/utils/misc.py +48 -0
  84. veadk/utils/volcengine_sign.py +6 -2
  85. veadk/version.py +1 -1
  86. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/METADATA +2 -1
  87. veadk_python-0.2.7.dist-info/RECORD +172 -0
  88. veadk_python-0.2.5.dist-info/RECORD +0 -127
  89. /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/__init__.py +0 -0
  90. /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/agent.py +0 -0
  91. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/WHEEL +0 -0
  92. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/entry_points.txt +0 -0
  93. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/licenses/LICENSE +0 -0
  94. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,53 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}文章管理{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="admin-posts">
7
+ <div class="admin-header">
8
+ <h2>文章管理</h2>
9
+ <a href="{{ url_for('admin_edit_post') }}" class="btn">新建文章</a>
10
+ </div>
11
+
12
+ <table class="posts-table">
13
+ <thead>
14
+ <tr>
15
+ <th>标题</th>
16
+ <th>发布时间</th>
17
+ <th>操作</th>
18
+ </tr>
19
+ </thead>
20
+ <tbody>
21
+ {% for post in posts.items %}
22
+ <tr>
23
+ <td><a href="{{ url_for('post_detail', post_id=post.id) }}">{{ post.title }}</a></td>
24
+ <td>{{ post.created_at.strftime('%Y-%m-%d %H:%M') }}</td>
25
+ <td>
26
+ <a href="{{ url_for('admin_edit_post', post_id=post.id) }}">编辑</a>
27
+ <form action="{{ url_for('admin_delete_post', post_id=post.id) }}" method="POST" style="display:inline;">
28
+ <button type="submit" class="delete-btn" onclick="return confirm('确定要删除这篇文章吗?')">删除</button>
29
+ </form>
30
+ </td>
31
+ </tr>
32
+ {% else %}
33
+ <tr>
34
+ <td colspan="3">暂无文章</td>
35
+ </tr>
36
+ {% endfor %}
37
+ </tbody>
38
+ </table>
39
+
40
+ <!-- 分页 -->
41
+ <div class="pagination">
42
+ {% if posts.has_prev %}
43
+ <a href="{{ url_for('admin_posts', page=posts.prev_num) }}">&laquo; 上一页</a>
44
+ {% endif %}
45
+
46
+ <span>第 {{ posts.page }} 页,共 {{ posts.pages }} 页</span>
47
+
48
+ {% if posts.has_next %}
49
+ <a href="{{ url_for('admin_posts', page=posts.next_num) }}">下一页 &raquo;</a>
50
+ {% endif %}
51
+ </div>
52
+ </div>
53
+ {% endblock %}
@@ -0,0 +1,45 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{% block title %}博客系统{% endblock %}</title>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
8
+ </head>
9
+ <body>
10
+ <header>
11
+ <div class="container">
12
+ <h1><a href="{{ url_for('index') }}">我的博客</a></h1>
13
+ <nav>
14
+ <a href="{{ url_for('index') }}">首页</a>
15
+ {% if session.admin_logged_in %}
16
+ <a href="{{ url_for('admin_dashboard') }}">管理后台</a>
17
+ <a href="{{ url_for('admin_logout') }}">退出</a>
18
+ {% else %}
19
+ <a href="{{ url_for('admin_login') }}">登录</a>
20
+ {% endif %}
21
+ </nav>
22
+ </div>
23
+ </header>
24
+
25
+ <main class="container">
26
+ {% with messages = get_flashed_messages() %}
27
+ {% if messages %}
28
+ <div class="flash-messages">
29
+ {% for message in messages %}
30
+ <div class="flash-message">{{ message }}</div>
31
+ {% endfor %}
32
+ </div>
33
+ {% endif %}
34
+ {% endwith %}
35
+
36
+ {% block content %}{% endblock %}
37
+ </main>
38
+
39
+ <footer>
40
+ <div class="container">
41
+ <p>&copy; 2023 我的博客. All rights reserved.</p>
42
+ </div>
43
+ </footer>
44
+ </body>
45
+ </html>
@@ -0,0 +1,29 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div class="posts">
5
+ {% for post in posts.items %}
6
+ <article class="post-preview">
7
+ <h2><a href="{{ url_for('post_detail', post_id=post.id) }}">{{ post.title }}</a></h2>
8
+ <p class="post-meta">发布于 {{ post.created_at.strftime('%Y-%m-%d %H:%M') }}</p>
9
+ <p>{{ post.content[:200] }}{% if post.content|length > 200 %}...{% endif %}</p>
10
+ <a href="{{ url_for('post_detail', post_id=post.id) }}" class="read-more">阅读全文</a>
11
+ </article>
12
+ {% else %}
13
+ <p>暂无文章。</p>
14
+ {% endfor %}
15
+ </div>
16
+
17
+ <!-- 分页 -->
18
+ <div class="pagination">
19
+ {% if posts.has_prev %}
20
+ <a href="{{ url_for('index', page=posts.prev_num) }}">&laquo; 上一页</a>
21
+ {% endif %}
22
+
23
+ <span>第 {{ posts.page }} 页,共 {{ posts.pages }} 页</span>
24
+
25
+ {% if posts.has_next %}
26
+ <a href="{{ url_for('index', page=posts.next_num) }}">下一页 &raquo;</a>
27
+ {% endif %}
28
+ </div>
29
+ {% endblock %}
@@ -0,0 +1,14 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}{{ post.title }} - 博客系统{% endblock %}
4
+
5
+ {% block content %}
6
+ <article class="post-detail">
7
+ <h1>{{ post.title }}</h1>
8
+ <p class="post-meta">发布于 {{ post.created_at.strftime('%Y-%m-%d %H:%M') }}</p>
9
+ <div class="post-content">
10
+ {{ post.content|replace('\n', '<br>')|safe }}
11
+ </div>
12
+ <a href="{{ url_for('index') }}" class="back-link">&laquo; 返回首页</a>
13
+ </article>
14
+ {% endblock %}
@@ -65,12 +65,15 @@ class VePromptPilot:
65
65
  api_key=self.api_key,
66
66
  ): # stream chunks of optimized prompt
67
67
  # Process each chunk as it arrives
68
- optimized_prompt += chunk.data.content
68
+ optimized_prompt += chunk.data.content if chunk.data else ""
69
69
  # print(chunk.data.content, end="", flush=True)
70
70
  if chunk.event == "usage":
71
- usage = chunk.data.usage
71
+ usage = chunk.data.usage if chunk.data else 0
72
72
  optimized_prompt = optimized_prompt.replace("\\n", "\n")
73
73
  print(f"Optimized prompt for agent {agent.name}:\n{optimized_prompt}")
74
- logger.info(f"Token usage: {usage['total_tokens']}")
74
+ if usage:
75
+ logger.info(f"Token usage: {usage['total_tokens']}")
76
+ else:
77
+ logger.warning("No usage data.")
75
78
 
76
79
  return optimized_prompt
@@ -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,117 @@
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 hashlib
16
+ import json
17
+ from typing import Any, Literal
18
+
19
+ import httpx
20
+ from volcengine.ApiInfo import ApiInfo
21
+ from volcengine.auth.SignerV4 import SignerV4
22
+ from volcengine.tls.const import (
23
+ APPLICATION_JSON,
24
+ CONTENT_MD5,
25
+ CONTENT_TYPE,
26
+ DATA,
27
+ WEB_TRACKS,
28
+ )
29
+ from volcengine.tls.TLSService import TLSService
30
+
31
+ from veadk.utils.logger import get_logger
32
+
33
+ logger = get_logger(__name__)
34
+
35
+ HEADER_API_VERSION = "x-tls-apiversion"
36
+ API_VERSION_V_0_3_0 = "0.3.0"
37
+
38
+ API_INFO = {
39
+ "CreateProject": ApiInfo("POST", "/CreateProject", {}, {}, {}),
40
+ "DescribeProjects": ApiInfo("GET", "/DescribeProjects", {}, {}, {}),
41
+ "CreateTraceInstance": ApiInfo("POST", "/CreateTraceInstance", {}, {}, {}),
42
+ "DescribeTraceInstances": ApiInfo("GET", "/DescribeTraceInstances", {}, {}, {}),
43
+ "DescribeTraceInstance": ApiInfo("GET", "/DescribeTraceInstance", {}, {}, {}),
44
+ }
45
+
46
+
47
+ def __prepare_request(
48
+ client: TLSService,
49
+ api: str,
50
+ params: dict | None = None,
51
+ body: Any | None = None,
52
+ request_headers: dict | None = None,
53
+ ):
54
+ if params is None:
55
+ params = {}
56
+ if body is None:
57
+ body = {}
58
+
59
+ request = client.prepare_request(API_INFO[api], params)
60
+
61
+ if request_headers is None:
62
+ request_headers = {CONTENT_TYPE: APPLICATION_JSON}
63
+ request.headers.update(request_headers)
64
+
65
+ if "json" in request.headers[CONTENT_TYPE] and api != WEB_TRACKS:
66
+ request.body = json.dumps(body)
67
+ else:
68
+ request.body = body[DATA]
69
+
70
+ if len(request.body) != 0:
71
+ if isinstance(request.body, str):
72
+ request.headers[CONTENT_MD5] = hashlib.md5(
73
+ request.body.encode("utf-8")
74
+ ).hexdigest()
75
+ else:
76
+ request.headers[CONTENT_MD5] = hashlib.md5(request.body).hexdigest()
77
+
78
+ SignerV4.sign(request, client.service_info.credentials)
79
+
80
+ return request
81
+
82
+
83
+ def ve_tls_request(
84
+ client: TLSService,
85
+ api: str,
86
+ params: dict | None = None,
87
+ body: dict | None = None,
88
+ request_headers: dict | None = None,
89
+ method: Literal["POST", "GET", "PUT", "DELETE"] = "POST",
90
+ ):
91
+ """Customize a standard HTTP request to the Volcengine TLS API"""
92
+
93
+ if request_headers is None:
94
+ request_headers = {HEADER_API_VERSION: API_VERSION_V_0_3_0}
95
+ elif HEADER_API_VERSION not in request_headers:
96
+ request_headers[HEADER_API_VERSION] = API_VERSION_V_0_3_0
97
+ if CONTENT_TYPE not in request_headers:
98
+ request_headers[CONTENT_TYPE] = APPLICATION_JSON
99
+ request = __prepare_request(client, api, params, body, request_headers)
100
+
101
+ url = request.build()
102
+
103
+ with httpx.Client() as session:
104
+ while True:
105
+ try:
106
+ response = session.request(
107
+ method=method,
108
+ url=url,
109
+ headers=request.headers,
110
+ data=request.body, # type: ignore
111
+ timeout=60,
112
+ )
113
+ return response.json()
114
+ except Exception as e:
115
+ logger.error(
116
+ f"Error occurred while making {method} request to {url}: {e}. Response: {response}"
117
+ )
@@ -0,0 +1,208 @@
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 os
16
+
17
+ from veadk.consts import DEFAULT_TLS_LOG_PROJECT_NAME, DEFAULT_TLS_TRACING_INSTANCE_NAME
18
+ from veadk.utils.logger import get_logger
19
+
20
+ logger = get_logger(__name__)
21
+
22
+
23
+ class VeTLS:
24
+ def __init__(
25
+ self,
26
+ access_key: str | None = None,
27
+ secret_key: str | None = None,
28
+ region: str = "cn-beijing",
29
+ ):
30
+ try:
31
+ from volcengine.tls.TLSService import TLSService
32
+
33
+ from veadk.integrations.ve_tls.utils import ve_tls_request
34
+ except ImportError:
35
+ raise ImportError(
36
+ "Please install volcengine SDK before init VeTLS: pip install volcengine"
37
+ )
38
+
39
+ self._ve_tls_request = ve_tls_request
40
+
41
+ self.access_key = (
42
+ access_key if access_key else os.getenv("VOLCENGINE_ACCESS_KEY", "")
43
+ )
44
+ self.secret_key = (
45
+ secret_key if secret_key else os.getenv("VOLCENGINE_SECRET_KEY", "")
46
+ )
47
+ self.region = region
48
+
49
+ self._client = TLSService(
50
+ endpoint=f"https://tls-{self.region}.volces.com",
51
+ access_key_id=self.access_key,
52
+ access_key_secret=self.secret_key,
53
+ region=self.region,
54
+ )
55
+
56
+ def get_project_id_by_name(self, project_name: str) -> str:
57
+ """Get the ID of a log project by its name.
58
+
59
+ Args:
60
+ project_name (str): The name of the log project.
61
+
62
+ Returns:
63
+ str: The ID of the log project, or None if not found.
64
+ """
65
+ logger.info(f"Getting ID for log project '{project_name}' in TLS...")
66
+
67
+ request_body = {
68
+ "ProjectName": project_name,
69
+ "IsFullName": True,
70
+ }
71
+
72
+ try:
73
+ res = None
74
+ res = self._ve_tls_request(
75
+ client=self._client,
76
+ api="DescribeProjects",
77
+ body=request_body,
78
+ method="GET",
79
+ )
80
+ projects = res["Projects"]
81
+ for project in projects:
82
+ if project["ProjectName"] == project_name:
83
+ return project["ProjectId"]
84
+ return "<no_project_id_found>"
85
+ except KeyError:
86
+ raise ValueError(f"Failed to get log project ID: {res}")
87
+
88
+ def create_log_project(self, project_name: str) -> str:
89
+ """Create a log project in TLS.
90
+
91
+ Args:
92
+ project_name (str): The name of the log project to create.
93
+
94
+ Returns:
95
+ str: The ID of the created log project.
96
+ """
97
+ logger.info(f"Creating log project '{project_name}' in TLS...")
98
+
99
+ request_body = {
100
+ "ProjectName": project_name,
101
+ "Region": self.region,
102
+ "Description": "Created by Volcengine Agent Development Kit (VeADK)",
103
+ "Tags": [{"Key": "provider", "Value": "VeADK"}],
104
+ }
105
+ try:
106
+ res = self._ve_tls_request(
107
+ client=self._client, api="CreateProject", body=request_body
108
+ )
109
+
110
+ if res["ErrorCode"] == "ProjectAlreadyExist":
111
+ logger.debug(
112
+ f"Log project '{project_name}' already exists. Check its ID."
113
+ )
114
+ return self.get_project_id_by_name(project_name)
115
+
116
+ return res["ProjectId"]
117
+ except KeyError:
118
+ raise ValueError(f"Failed to create log project: {res}")
119
+
120
+ def get_trace_instance_by_name(self, log_project_id: str, trace_instance_name: str):
121
+ logger.info(f"Getting trace instance '{trace_instance_name}' in TLS...")
122
+
123
+ request_body = {
124
+ "PageSize": 100,
125
+ "ProjectId": log_project_id,
126
+ "TraceInstanceName": trace_instance_name,
127
+ }
128
+ try:
129
+ res = self._ve_tls_request(
130
+ client=self._client,
131
+ api="DescribeTraceInstances",
132
+ body=request_body,
133
+ method="GET",
134
+ )
135
+
136
+ for instance in res["TraceInstances"]:
137
+ if instance["TraceInstanceName"] == trace_instance_name:
138
+ return instance
139
+ except KeyError:
140
+ raise ValueError(f"Failed to create log project: {res}")
141
+
142
+ def create_tracing_instance(self, log_project_id: str, trace_instance_name: str):
143
+ """Create a tracing instance in TLS.
144
+
145
+ Args:
146
+ instance_name (str): The name of the tracing instance to create.
147
+
148
+ Returns:
149
+ dict: The tracing instance.
150
+ """
151
+ logger.info(f"Creating tracing instance '{trace_instance_name}' in TLS...")
152
+
153
+ request_body = {
154
+ "ProjectId": log_project_id,
155
+ "TraceInstanceName": trace_instance_name,
156
+ "Description": "Created by Volcengine Agent Development Kit (VeADK)",
157
+ }
158
+
159
+ try:
160
+ res = None
161
+ res = self._ve_tls_request(
162
+ client=self._client,
163
+ api="CreateTraceInstance",
164
+ body=request_body,
165
+ )
166
+
167
+ if res["ErrorCode"] == "TopicAlreadyExist":
168
+ logger.debug(
169
+ f"Log project '{trace_instance_name}' already exists. Check its ID."
170
+ )
171
+ return self.get_trace_instance_by_name(
172
+ log_project_id, trace_instance_name
173
+ )
174
+
175
+ # after creation, get the trace instance details
176
+ res = self._ve_tls_request(
177
+ client=self._client,
178
+ api="DescribeTraceInstance",
179
+ body={"TraceInstanceID": res["TraceInstanceID"]},
180
+ method="GET",
181
+ )
182
+
183
+ return res
184
+ except KeyError:
185
+ raise ValueError(f"Failed to create tracing instance: {res}")
186
+
187
+ def get_trace_topic_id(self):
188
+ """Get the trace topic ID under VeADK default names.
189
+
190
+ This method is a tool function just designed for `veadk/config.py`.
191
+
192
+ Returns:
193
+ str: The trace topic ID.
194
+ """
195
+ logger.info("Getting trace topic ID for tracing instance in TLS...")
196
+
197
+ log_project_id = self.create_log_project(DEFAULT_TLS_LOG_PROJECT_NAME)
198
+
199
+ instance = self.create_tracing_instance(
200
+ log_project_id, DEFAULT_TLS_TRACING_INSTANCE_NAME
201
+ )
202
+
203
+ if not instance:
204
+ raise ValueError("None instance")
205
+
206
+ logger.info(f"Fetched trace topic id: {instance['TraceTopicId']}")
207
+
208
+ return instance["TraceTopicId"]