coze-coding-utils 0.2.5__tar.gz → 0.2.6a1__tar.gz

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 (38) hide show
  1. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/PKG-INFO +1 -1
  2. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/pyproject.toml +1 -1
  3. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/helper/agent_helper.py +15 -93
  4. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/loop_trace.py +4 -0
  5. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/converter/request_converter.py +0 -22
  6. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/.gitignore +0 -0
  7. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/LICENSE +0 -0
  8. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/README.md +0 -0
  9. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/__init__.py +0 -0
  10. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/error/__init__.py +0 -0
  11. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/error/classifier.py +0 -0
  12. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/error/codes.py +0 -0
  13. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/error/exceptions.py +0 -0
  14. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/error/patterns.py +0 -0
  15. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/file/__init__.py +0 -0
  16. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/file/file.py +0 -0
  17. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/helper/__init__.py +0 -0
  18. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/helper/graph_helper.py +0 -0
  19. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/helper/stream_runner.py +0 -0
  20. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/__init__.py +0 -0
  21. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/common.py +0 -0
  22. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/config.py +0 -0
  23. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/err_trace.py +0 -0
  24. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/node_log.py +0 -0
  25. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/parser.py +0 -0
  26. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/log/write_log.py +0 -0
  27. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/messages/__init__.py +0 -0
  28. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/messages/client.py +0 -0
  29. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/messages/server.py +0 -0
  30. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/__init__.py +0 -0
  31. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/converter/__init__.py +0 -0
  32. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/converter/response_converter.py +0 -0
  33. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/handler.py +0 -0
  34. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/types/__init__.py +0 -0
  35. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/types/request.py +0 -0
  36. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/openai/types/response.py +0 -0
  37. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/runtime_ctx/__init__.py +0 -0
  38. {coze_coding_utils-0.2.5 → coze_coding_utils-0.2.6a1}/src/coze_coding_utils/runtime_ctx/context.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coze-coding-utils
3
- Version: 0.2.5
3
+ Version: 0.2.6a1
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "coze-coding-utils"
7
- version = "0.2.5"
7
+ version = "0.2.6a1"
8
8
  description = "Utilities for Coze coding client runtime context and helpers."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,8 +1,7 @@
1
1
  import uuid
2
2
  import json
3
- import requests
4
- from urllib.parse import urlparse, urlencode, parse_qs, urljoin
5
- from typing import Any, Dict, List, Tuple, Iterator, Optional
3
+ import os
4
+ from typing import Any, Dict, List, Tuple, Iterator
6
5
  import time
7
6
  from coze_coding_utils.file.file import File, FileOps, infer_file_category
8
7
  from coze_coding_utils.error import classify_error
@@ -32,78 +31,6 @@ from coze_coding_utils.messages.server import (
32
31
  )
33
32
 
34
33
 
35
- _VIDEO_MIME_MAP: Dict[str, str] = {
36
- "mp4": "video/mp4",
37
- "avi": "video/x-msvideo",
38
- "mov": "video/quicktime",
39
- "mkv": "video/x-matroska",
40
- "flv": "video/x-flv",
41
- "wmv": "video/x-ms-wmv",
42
- "webm": "video/webm",
43
- "m4v": "video/x-m4v",
44
- "3gp": "video/3gpp",
45
- }
46
-
47
- # 下游 LLM API 实际支持的视频 MIME 类型白名单
48
- _SUPPORTED_VIDEO_MIMES = {
49
- "video/mp4",
50
- "video/quicktime",
51
- "video/webm",
52
- "video/3gpp",
53
- "video/x-m4v",
54
- }
55
-
56
-
57
- def _probe_remote_mime(url: str) -> Optional[str]:
58
- """HEAD 请求探测远程文件的真实 Content-Type,失败时返回 None"""
59
- try:
60
- resp = requests.head(url, timeout=5, allow_redirects=True)
61
- ct = resp.headers.get("Content-Type", "")
62
- return ct.split(";")[0].strip() or None
63
- except Exception:
64
- return None
65
-
66
-
67
- def _ensure_video_content_type(url: str, mime_type: str) -> str:
68
- """
69
- 对象存储(TOS/S3)的 presigned URL 可能返回 application/octet-stream。
70
- 通过追加 response-content-type 参数让服务端在响应中覆盖 Content-Type,
71
- 从而使 LLM API fetch URL 时能拿到正确的 video MIME,而不会因 octet-stream 被拒。
72
- 已有签名不受影响(TOS/S3 response-* 参数不计入签名哈希)。
73
- """
74
- parsed = urlparse(url)
75
- # 已经有正确的 response-content-type,不重复添加
76
- qs = parse_qs(parsed.query, keep_blank_values=True)
77
- if qs.get("response-content-type") == [mime_type]:
78
- return url
79
- sep = "&" if parsed.query else "?"
80
- return url + sep + "response-content-type=" + requests.utils.quote(mime_type, safe="")
81
-
82
-
83
- def _build_video_parts(
84
- file_data: File, file_info: Any, file_ext: str, mime_override: Optional[str] = None
85
- ) -> List[Dict[str, Any]]:
86
- """将视频文件转换为 content_parts,不支持的格式退化为文本描述。
87
- mime_override: 外部已探测好的 MIME,传入时跳过内部探测,避免重复 HEAD 请求。
88
- """
89
- ext = file_ext.lstrip(".").lower()
90
- mime_type = mime_override or _VIDEO_MIME_MAP.get(ext)
91
- if not mime_type and file_data.is_remote:
92
- mime_type = _probe_remote_mime(file_info.url)
93
-
94
- if mime_type and mime_type in _SUPPORTED_VIDEO_MIMES:
95
- # 追加 response-content-type 参数,确保对象存储返回正确的 Content-Type
96
- # 防止 LLM API fetch URL 时因拿到 application/octet-stream 而报错
97
- video_url = _ensure_video_content_type(file_info.url, mime_type) if file_data.is_remote else file_info.url
98
- return [
99
- {"type": "text", "text": f'{file_data.url}'},
100
- {"type": "video_url", "video_url": {"url": video_url, "media_type": mime_type}},
101
- ]
102
- else:
103
- fmt_hint = mime_type or (f".{ext}" if ext else "unknown")
104
- return [{"type": "text", "text": f"video url: {file_info.url} (format: {fmt_hint})"}]
105
-
106
-
107
34
  def to_stream_input(msg: ClientMessage) -> Dict[str, Any]:
108
35
  content_parts = []
109
36
  if msg and msg.content and msg.content.query and msg.content.query.prompt:
@@ -116,23 +43,7 @@ def to_stream_input(msg: ClientMessage) -> Dict[str, Any]:
116
43
  and block.content.upload_file
117
44
  ):
118
45
  file_info = block.content.upload_file
119
- # 第一轮:从 URL 后缀识别类型
120
- file_type, file_ext = infer_file_category(file_info.url)
121
- # 第二轮:URL 无后缀时用 file_name 兜底
122
- if file_type == "default" and file_info.file_name:
123
- file_type, file_ext = infer_file_category(file_info.file_name)
124
- # 第三轮:两轮扩展名都无法识别时,HEAD 探测真实 Content-Type
125
- probed_mime: Optional[str] = None
126
- if file_type == "default" and file_info.url.startswith(("http://", "https://")):
127
- probed_mime = _probe_remote_mime(file_info.url)
128
- if probed_mime:
129
- top = probed_mime.split("/")[0]
130
- if top == "video":
131
- file_type = "video"
132
- elif top == "image":
133
- file_type = "image"
134
- elif top == "audio":
135
- file_type = "audio"
46
+ file_type, _ = infer_file_category(file_info.url)
136
47
  file_data = File(url=file_info.url, file_type=file_type)
137
48
  # check is image
138
49
  if file_data.file_type == "image":
@@ -150,7 +61,18 @@ def to_stream_input(msg: ClientMessage) -> Dict[str, Any]:
150
61
  )
151
62
  # check is video
152
63
  elif file_data.file_type == "video":
153
- content_parts.extend(_build_video_parts(file_data, file_info, file_ext, probed_mime))
64
+ content_parts.append(
65
+ {
66
+ "type": "text",
67
+ "text": f'{file_data.url}'
68
+ }
69
+ )
70
+ content_parts.append(
71
+ {
72
+ "type": "video_url",
73
+ "video_url": {"url": file_info.url},
74
+ }
75
+ )
154
76
  # check is audio
155
77
  elif file_data.file_type == "audio":
156
78
  content_parts.append(
@@ -31,6 +31,8 @@ def init_run_config(graph, ctx):
31
31
  "execute_mode": get_execute_mode(),
32
32
  "log_id": ctx.logid,
33
33
  "commit_hash": commit_hash,
34
+ "coze_entity_type": ctx.rpc_persist_res_rec_root_entity_type,
35
+ "coze_entity_id": ctx.rpc_persist_res_rec_root_entity_id,
34
36
  }
35
37
  )
36
38
  config = RunnableConfig(
@@ -52,6 +54,8 @@ def init_agent_config(graph, ctx):
52
54
  "execute_mode": get_execute_mode(),
53
55
  "log_id": ctx.logid,
54
56
  "commit_hash": commit_hash,
57
+ "coze_entity_type": ctx.rpc_persist_res_rec_root_entity_type,
58
+ "coze_entity_id": ctx.rpc_persist_res_rec_root_entity_id,
55
59
  }
56
60
  )
57
61
  ]
@@ -6,10 +6,6 @@ from coze_coding_utils.openai.types.request import (
6
6
  ChatMessage,
7
7
  )
8
8
  from coze_coding_utils.file.file import File, FileOps, infer_file_category
9
- from coze_coding_utils.helper.agent_helper import (
10
- _VIDEO_MIME_MAP,
11
- _ensure_video_content_type,
12
- )
13
9
 
14
10
 
15
11
  class RequestConverter:
@@ -114,15 +110,6 @@ class RequestConverter:
114
110
  video_url_data = part.get("video_url", {})
115
111
  url = video_url_data.get("url", "")
116
112
  if url:
117
- _, file_ext = infer_file_category(url)
118
- ext = file_ext.lstrip(".").lower()
119
- mime_type = _VIDEO_MIME_MAP.get(ext)
120
- if mime_type:
121
- fixed_url = _ensure_video_content_type(url, mime_type)
122
- return [
123
- {"type": "text", "text": url},
124
- {"type": "video_url", "video_url": {"url": fixed_url, "media_type": mime_type}},
125
- ]
126
113
  return [
127
114
  {"type": "text", "text": url},
128
115
  {"type": "video_url", "video_url": {"url": url}},
@@ -160,15 +147,6 @@ class RequestConverter:
160
147
  {"type": "image_url", "image_url": {"url": url}},
161
148
  ]
162
149
  elif file_type == "video":
163
- _, file_ext = infer_file_category(url)
164
- ext = file_ext.lstrip(".").lower()
165
- mime_type = _VIDEO_MIME_MAP.get(ext)
166
- if mime_type:
167
- fixed_url = _ensure_video_content_type(url, mime_type)
168
- return [
169
- {"type": "text", "text": url},
170
- {"type": "video_url", "video_url": {"url": fixed_url, "media_type": mime_type}},
171
- ]
172
150
  return [
173
151
  {"type": "text", "text": url},
174
152
  {"type": "video_url", "video_url": {"url": url}},