coze-coding-utils 0.2.0__py3-none-any.whl → 0.2.1__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.
- coze_coding_utils/__init__.py +1 -1
- {coze_coding_utils-0.2.0.dist-info → coze_coding_utils-0.2.1.dist-info}/METADATA +2 -17
- coze_coding_utils-0.2.1.dist-info/RECORD +7 -0
- coze_coding_utils/error/__init__.py +0 -31
- coze_coding_utils/error/classifier.py +0 -320
- coze_coding_utils/error/codes.py +0 -356
- coze_coding_utils/error/exceptions.py +0 -439
- coze_coding_utils/error/patterns.py +0 -939
- coze_coding_utils/error/test_classifier.py +0 -0
- coze_coding_utils/file/__init__.py +0 -0
- coze_coding_utils/file/file.py +0 -327
- coze_coding_utils/helper/__init__.py +0 -0
- coze_coding_utils/helper/agent_helper.py +0 -599
- coze_coding_utils/helper/graph_helper.py +0 -231
- coze_coding_utils/log/__init__.py +0 -0
- coze_coding_utils/log/common.py +0 -8
- coze_coding_utils/log/config.py +0 -10
- coze_coding_utils/log/err_trace.py +0 -88
- coze_coding_utils/log/loop_trace.py +0 -72
- coze_coding_utils/log/node_log.py +0 -487
- coze_coding_utils/log/parser.py +0 -255
- coze_coding_utils/log/write_log.py +0 -183
- coze_coding_utils/messages/__init__.py +0 -0
- coze_coding_utils/messages/client.py +0 -48
- coze_coding_utils/messages/server.py +0 -173
- coze_coding_utils/openai/__init__.py +0 -5
- coze_coding_utils/openai/converter/__init__.py +0 -6
- coze_coding_utils/openai/converter/request_converter.py +0 -165
- coze_coding_utils/openai/converter/response_converter.py +0 -467
- coze_coding_utils/openai/handler.py +0 -298
- coze_coding_utils/openai/types/__init__.py +0 -37
- coze_coding_utils/openai/types/request.py +0 -24
- coze_coding_utils/openai/types/response.py +0 -178
- coze_coding_utils-0.2.0.dist-info/RECORD +0 -37
- {coze_coding_utils-0.2.0.dist-info → coze_coding_utils-0.2.1.dist-info}/WHEEL +0 -0
- {coze_coding_utils-0.2.0.dist-info → coze_coding_utils-0.2.1.dist-info}/licenses/LICENSE +0 -0
coze_coding_utils/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coze-coding-utils
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Utilities for Coze coding client runtime context and helpers.
|
|
5
5
|
Project-URL: Homepage, https://code.byted.org/stone/coze-coding-client
|
|
6
6
|
Author: Bytedance Stone Team
|
|
@@ -12,21 +12,6 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Requires-Python: >=3.10
|
|
15
|
-
Requires-Dist: docx2python==3.5.0
|
|
16
|
-
Requires-Dist: fastapi==0.121.2
|
|
17
|
-
Requires-Dist: langchain-core==1.0.2
|
|
18
|
-
Requires-Dist: langchain-openai==1.0.1
|
|
19
|
-
Requires-Dist: langchain==1.0.3
|
|
20
|
-
Requires-Dist: langgraph-checkpoint==3.0.0
|
|
21
|
-
Requires-Dist: langgraph-prebuilt==1.0.2
|
|
22
|
-
Requires-Dist: langgraph-sdk==0.2.9
|
|
23
|
-
Requires-Dist: langgraph==1.0.2
|
|
24
|
-
Requires-Dist: langsmith==0.4.39
|
|
25
|
-
Requires-Dist: openpyxl==3.1.5
|
|
26
|
-
Requires-Dist: pydantic-core==2.41.4
|
|
27
|
-
Requires-Dist: pydantic==2.12.3
|
|
28
|
-
Requires-Dist: pypdf==6.4.1
|
|
29
|
-
Requires-Dist: python-pptx==1.0.2
|
|
30
15
|
Description-Content-Type: text/markdown
|
|
31
16
|
|
|
32
17
|
# coze-coding-utils
|
|
@@ -54,4 +39,4 @@ Requires Python 3.10+.
|
|
|
54
39
|
|
|
55
40
|
## License
|
|
56
41
|
|
|
57
|
-
MIT
|
|
42
|
+
MIT
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
coze_coding_utils/__init__.py,sha256=dQtSrS3n4kQxFmK2BrA9n_e5r6YJEMGZ3enaYv-VLeg,36
|
|
2
|
+
coze_coding_utils/runtime_ctx/__init__.py,sha256=4W8VliAYUP1KY2gLJ_YDy2TmcXYVm-PY7XikQD_bFwA,2
|
|
3
|
+
coze_coding_utils/runtime_ctx/context.py,sha256=G8ld-WnQ1pTJe5OOXC_dTbagXj9IxmpRiPM4X_jWW6o,3992
|
|
4
|
+
coze_coding_utils-0.2.1.dist-info/METADATA,sha256=PaeCjKPUN4nvLGpUYFo0BgyBmHbK9nhozzWxv2Efs-0,978
|
|
5
|
+
coze_coding_utils-0.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
+
coze_coding_utils-0.2.1.dist-info/licenses/LICENSE,sha256=lzckZhAjHlpSJcWvppoST095IHFpBwKiB2pKcBv7vP4,1078
|
|
7
|
+
coze_coding_utils-0.2.1.dist-info/RECORD,,
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
VibeCoding Error Module
|
|
3
|
-
|
|
4
|
-
6位错误码体系设计:
|
|
5
|
-
- 第1位: 错误大类 (1-9)
|
|
6
|
-
- 第2-3位: 错误子类 (01-99)
|
|
7
|
-
- 第4-6位: 具体错误 (001-999)
|
|
8
|
-
|
|
9
|
-
错误大类:
|
|
10
|
-
1xxxxx - 代码语法/类型错误 (Code Syntax/Type Errors)
|
|
11
|
-
2xxxxx - 输入验证错误 (Input Validation Errors)
|
|
12
|
-
3xxxxx - 外部API错误 (External API Errors)
|
|
13
|
-
4xxxxx - 资源/文件错误 (Resource/File Errors)
|
|
14
|
-
5xxxxx - 集成服务错误 (Integration Service Errors)
|
|
15
|
-
6xxxxx - 业务逻辑错误 (Business Logic Errors)
|
|
16
|
-
7xxxxx - 运行时错误 (Runtime Errors)
|
|
17
|
-
8xxxxx - 配置错误 (Configuration Errors)
|
|
18
|
-
9xxxxx - 未知错误 (Unknown Errors)
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
from .codes import ErrorCode, ErrorCategory
|
|
22
|
-
from .exceptions import VibeCodingError, classify_error
|
|
23
|
-
from .classifier import ErrorClassifier
|
|
24
|
-
|
|
25
|
-
__all__ = [
|
|
26
|
-
"ErrorCode",
|
|
27
|
-
"ErrorCategory",
|
|
28
|
-
"VibeCodingError",
|
|
29
|
-
"classify_error",
|
|
30
|
-
"ErrorClassifier",
|
|
31
|
-
]
|
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
错误分类器 - 提供高层API用于错误分析和统计
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import logging
|
|
6
|
-
import re
|
|
7
|
-
from collections import defaultdict
|
|
8
|
-
from dataclasses import dataclass, field
|
|
9
|
-
from typing import Optional, Dict, Any, List
|
|
10
|
-
|
|
11
|
-
from .codes import ErrorCategory, get_error_description
|
|
12
|
-
from .exceptions import VibeCodingError, classify_error
|
|
13
|
-
from ..log.err_trace import extract_core_stack
|
|
14
|
-
|
|
15
|
-
logger = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@dataclass
|
|
19
|
-
class ErrorInfo:
|
|
20
|
-
"""错误信息结构"""
|
|
21
|
-
code: int
|
|
22
|
-
message: str
|
|
23
|
-
category: ErrorCategory
|
|
24
|
-
category_name: str
|
|
25
|
-
description: str
|
|
26
|
-
original_type: str = ""
|
|
27
|
-
original_message: str = ""
|
|
28
|
-
node_name: str = ""
|
|
29
|
-
task_id: str = ""
|
|
30
|
-
|
|
31
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
32
|
-
return {
|
|
33
|
-
"code": self.code,
|
|
34
|
-
"message": self.message,
|
|
35
|
-
"category": self.category.value,
|
|
36
|
-
"category_name": self.category_name,
|
|
37
|
-
"description": self.description,
|
|
38
|
-
"original_type": self.original_type,
|
|
39
|
-
"node_name": self.node_name,
|
|
40
|
-
"task_id": self.task_id,
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@dataclass
|
|
45
|
-
class ErrorStats:
|
|
46
|
-
"""错误统计结构"""
|
|
47
|
-
total_count: int = 0
|
|
48
|
-
by_category: Dict[str, int] = field(default_factory=lambda: defaultdict(int))
|
|
49
|
-
by_code: Dict[int, int] = field(default_factory=lambda: defaultdict(int))
|
|
50
|
-
by_node: Dict[str, int] = field(default_factory=lambda: defaultdict(int))
|
|
51
|
-
recent_errors: List[ErrorInfo] = field(default_factory=list)
|
|
52
|
-
|
|
53
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
54
|
-
return {
|
|
55
|
-
"total_count": self.total_count,
|
|
56
|
-
"by_category": dict(self.by_category),
|
|
57
|
-
"by_code": {str(k): v for k, v in self.by_code.items()},
|
|
58
|
-
"by_node": dict(self.by_node),
|
|
59
|
-
"recent_errors": [e.to_dict() for e in self.recent_errors[-10:]], # 最近10个错误
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class ErrorClassifier:
|
|
64
|
-
"""
|
|
65
|
-
错误分类器
|
|
66
|
-
|
|
67
|
-
提供:
|
|
68
|
-
1. 异常分类: classify() - 将异常转换为带错误码的VibeCodingError
|
|
69
|
-
2. 错误信息提取: extract_error_info() - 从异常提取结构化错误信息
|
|
70
|
-
3. 错误统计: 记录和统计错误分布
|
|
71
|
-
"""
|
|
72
|
-
|
|
73
|
-
def __init__(self, max_recent_errors: int = 100):
|
|
74
|
-
self._stats = ErrorStats()
|
|
75
|
-
self._max_recent_errors = max_recent_errors
|
|
76
|
-
|
|
77
|
-
def classify(
|
|
78
|
-
self,
|
|
79
|
-
error: BaseException,
|
|
80
|
-
context: Optional[Dict[str, Any]] = None
|
|
81
|
-
) -> VibeCodingError:
|
|
82
|
-
"""
|
|
83
|
-
分类错误并返回VibeCodingError
|
|
84
|
-
|
|
85
|
-
Args:
|
|
86
|
-
error: 原始异常
|
|
87
|
-
context: 额外上下文 (如 node_name, task_id 等)
|
|
88
|
-
|
|
89
|
-
Returns:
|
|
90
|
-
VibeCodingError: 带有6位错误码的异常
|
|
91
|
-
"""
|
|
92
|
-
err = classify_error(error, context)
|
|
93
|
-
|
|
94
|
-
# 更新统计
|
|
95
|
-
self._update_stats(err, context)
|
|
96
|
-
|
|
97
|
-
return err
|
|
98
|
-
|
|
99
|
-
def extract_error_info(
|
|
100
|
-
self,
|
|
101
|
-
error: BaseException,
|
|
102
|
-
context: Optional[Dict[str, Any]] = None
|
|
103
|
-
) -> ErrorInfo:
|
|
104
|
-
"""
|
|
105
|
-
从异常提取结构化错误信息
|
|
106
|
-
|
|
107
|
-
Args:
|
|
108
|
-
error: 原始异常
|
|
109
|
-
context: 额外上下文
|
|
110
|
-
|
|
111
|
-
Returns:
|
|
112
|
-
ErrorInfo: 结构化错误信息
|
|
113
|
-
"""
|
|
114
|
-
err = classify_error(error, context)
|
|
115
|
-
ctx = context or {}
|
|
116
|
-
|
|
117
|
-
return ErrorInfo(
|
|
118
|
-
code=err.code,
|
|
119
|
-
message=err.message,
|
|
120
|
-
category=err.category,
|
|
121
|
-
category_name=err.category.name,
|
|
122
|
-
description=get_error_description(err.code),
|
|
123
|
-
original_type=type(error).__name__,
|
|
124
|
-
original_message=str(error)[:500],
|
|
125
|
-
node_name=ctx.get("node_name", ""),
|
|
126
|
-
task_id=ctx.get("task_id", ""),
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
def get_error_code(
|
|
130
|
-
self,
|
|
131
|
-
error: BaseException,
|
|
132
|
-
context: Optional[Dict[str, Any]] = None
|
|
133
|
-
) -> int:
|
|
134
|
-
"""
|
|
135
|
-
获取错误码 (简化接口)
|
|
136
|
-
|
|
137
|
-
Args:
|
|
138
|
-
error: 原始异常
|
|
139
|
-
context: 额外上下文
|
|
140
|
-
|
|
141
|
-
Returns:
|
|
142
|
-
int: 6位错误码
|
|
143
|
-
"""
|
|
144
|
-
err = classify_error(error, context)
|
|
145
|
-
return err.code
|
|
146
|
-
|
|
147
|
-
def get_error_response(
|
|
148
|
-
self,
|
|
149
|
-
error: BaseException,
|
|
150
|
-
context: Optional[Dict[str, Any]] = None
|
|
151
|
-
) -> Dict[str, Any]:
|
|
152
|
-
"""
|
|
153
|
-
获取用于API响应的错误信息
|
|
154
|
-
|
|
155
|
-
Args:
|
|
156
|
-
error: 原始异常
|
|
157
|
-
context: 额外上下文
|
|
158
|
-
|
|
159
|
-
Returns:
|
|
160
|
-
dict: 包含 code, message, category 的字典
|
|
161
|
-
"""
|
|
162
|
-
err = self.classify(error, context)
|
|
163
|
-
logger.error(f"Error classifier classify error: {error}, traceback: {extract_core_stack()}, get error code: {err.code}, error message: {err.message}, error category: {err.category.name}")
|
|
164
|
-
|
|
165
|
-
return {
|
|
166
|
-
"error_code": err.code,
|
|
167
|
-
"error_message": err.message,
|
|
168
|
-
"error_category": err.category.name,
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
def _update_stats(
|
|
172
|
-
self,
|
|
173
|
-
error: VibeCodingError,
|
|
174
|
-
context: Optional[Dict[str, Any]] = None
|
|
175
|
-
):
|
|
176
|
-
"""更新错误统计"""
|
|
177
|
-
ctx = context or {}
|
|
178
|
-
|
|
179
|
-
self._stats.total_count += 1
|
|
180
|
-
self._stats.by_category[error.category.name] += 1
|
|
181
|
-
self._stats.by_code[error.code] += 1
|
|
182
|
-
|
|
183
|
-
node_name = ctx.get("node_name", "unknown")
|
|
184
|
-
if node_name:
|
|
185
|
-
self._stats.by_node[node_name] += 1
|
|
186
|
-
|
|
187
|
-
# 记录最近的错误
|
|
188
|
-
error_info = ErrorInfo(
|
|
189
|
-
code=error.code,
|
|
190
|
-
message=error.message,
|
|
191
|
-
category=error.category,
|
|
192
|
-
category_name=error.category.name,
|
|
193
|
-
description=get_error_description(error.code),
|
|
194
|
-
original_type=ctx.get("original_type", ""),
|
|
195
|
-
original_message=ctx.get("original_message", "")[:200],
|
|
196
|
-
node_name=node_name,
|
|
197
|
-
task_id=ctx.get("task_id", ""),
|
|
198
|
-
)
|
|
199
|
-
self._stats.recent_errors.append(error_info)
|
|
200
|
-
|
|
201
|
-
# 限制最近错误数量
|
|
202
|
-
if len(self._stats.recent_errors) > self._max_recent_errors:
|
|
203
|
-
self._stats.recent_errors = self._stats.recent_errors[-self._max_recent_errors:]
|
|
204
|
-
|
|
205
|
-
def get_stats(self) -> ErrorStats:
|
|
206
|
-
"""获取错误统计"""
|
|
207
|
-
return self._stats
|
|
208
|
-
|
|
209
|
-
def reset_stats(self):
|
|
210
|
-
"""重置统计"""
|
|
211
|
-
self._stats = ErrorStats()
|
|
212
|
-
|
|
213
|
-
@staticmethod
|
|
214
|
-
def parse_error_from_log(log_line: str) -> Optional[ErrorInfo]:
|
|
215
|
-
"""
|
|
216
|
-
从日志行解析错误信息
|
|
217
|
-
|
|
218
|
-
支持解析格式:
|
|
219
|
-
- "During task with name 'xxx' and id 'xxx'"
|
|
220
|
-
- "Before task with name 'xxx'"
|
|
221
|
-
- 标准 Python Traceback
|
|
222
|
-
|
|
223
|
-
Args:
|
|
224
|
-
log_line: 日志行
|
|
225
|
-
|
|
226
|
-
Returns:
|
|
227
|
-
ErrorInfo: 解析出的错误信息,解析失败返回None
|
|
228
|
-
"""
|
|
229
|
-
try:
|
|
230
|
-
# 提取任务名称
|
|
231
|
-
node_match = re.search(r"(?:During|Before) task with name '(\w+)'", log_line)
|
|
232
|
-
node_name = node_match.group(1) if node_match else ""
|
|
233
|
-
|
|
234
|
-
# 提取任务ID
|
|
235
|
-
task_match = re.search(r"id '([a-f0-9-]+)'", log_line)
|
|
236
|
-
task_id = task_match.group(1) if task_match else ""
|
|
237
|
-
|
|
238
|
-
# 提取错误类型和消息
|
|
239
|
-
# 格式1: "ExceptionType: message"
|
|
240
|
-
error_match = re.search(r"(\w+Error|\w+Exception): (.+?)(?:\"|\]|$)", log_line)
|
|
241
|
-
if not error_match:
|
|
242
|
-
# 格式2: 在 Traceback 列表中
|
|
243
|
-
error_match = re.search(r"'(\w+Error|\w+Exception): (.+?)'", log_line)
|
|
244
|
-
|
|
245
|
-
if error_match:
|
|
246
|
-
error_type = error_match.group(1)
|
|
247
|
-
error_message = error_match.group(2)
|
|
248
|
-
|
|
249
|
-
# 创建模拟异常进行分类
|
|
250
|
-
mock_error = _create_mock_exception(error_type, error_message)
|
|
251
|
-
err = classify_error(mock_error, {"node_name": node_name, "task_id": task_id})
|
|
252
|
-
|
|
253
|
-
return ErrorInfo(
|
|
254
|
-
code=err.code,
|
|
255
|
-
message=err.message,
|
|
256
|
-
category=err.category,
|
|
257
|
-
category_name=err.category.name,
|
|
258
|
-
description=get_error_description(err.code),
|
|
259
|
-
original_type=error_type,
|
|
260
|
-
original_message=error_message[:200],
|
|
261
|
-
node_name=node_name,
|
|
262
|
-
task_id=task_id,
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
return None
|
|
266
|
-
|
|
267
|
-
except Exception as e:
|
|
268
|
-
logger.warning(f"Failed to parse error from log: {e}")
|
|
269
|
-
return None
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
def _create_mock_exception(error_type: str, error_message: str) -> BaseException:
|
|
273
|
-
"""创建模拟异常用于分类"""
|
|
274
|
-
exception_map = {
|
|
275
|
-
"AttributeError": AttributeError,
|
|
276
|
-
"TypeError": TypeError,
|
|
277
|
-
"ValueError": ValueError,
|
|
278
|
-
"KeyError": KeyError,
|
|
279
|
-
"IndexError": IndexError,
|
|
280
|
-
"NameError": NameError,
|
|
281
|
-
"ImportError": ImportError,
|
|
282
|
-
"ModuleNotFoundError": ModuleNotFoundError,
|
|
283
|
-
"SyntaxError": SyntaxError,
|
|
284
|
-
"IndentationError": IndentationError,
|
|
285
|
-
"RuntimeError": RuntimeError,
|
|
286
|
-
"NotImplementedError": NotImplementedError,
|
|
287
|
-
"TimeoutError": TimeoutError,
|
|
288
|
-
"FileNotFoundError": FileNotFoundError,
|
|
289
|
-
"IOError": IOError,
|
|
290
|
-
"OSError": OSError,
|
|
291
|
-
"MemoryError": MemoryError,
|
|
292
|
-
"RecursionError": RecursionError,
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
# Pydantic ValidationError 特殊处理
|
|
296
|
-
if "ValidationError" in error_type:
|
|
297
|
-
return Exception(f"ValidationError: {error_message}")
|
|
298
|
-
|
|
299
|
-
# API Error 特殊处理
|
|
300
|
-
if "APIError" in error_type:
|
|
301
|
-
return Exception(f"APIError: {error_message}")
|
|
302
|
-
|
|
303
|
-
exception_class = exception_map.get(error_type, Exception)
|
|
304
|
-
|
|
305
|
-
try:
|
|
306
|
-
return exception_class(error_message)
|
|
307
|
-
except Exception:
|
|
308
|
-
return Exception(f"{error_type}: {error_message}")
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
# 全局分类器实例 (单例模式)
|
|
312
|
-
_global_classifier: Optional[ErrorClassifier] = None
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
def get_classifier() -> ErrorClassifier:
|
|
316
|
-
"""获取全局错误分类器实例"""
|
|
317
|
-
global _global_classifier
|
|
318
|
-
if _global_classifier is None:
|
|
319
|
-
_global_classifier = ErrorClassifier()
|
|
320
|
-
return _global_classifier
|