coze_lab 0.1.40 → 0.1.41
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.
package/package.json
CHANGED
|
@@ -1071,7 +1071,7 @@ def _build_history_messages(history_turns: List[Dict[str, Any]]) -> list:
|
|
|
1071
1071
|
|
|
1072
1072
|
# --- CozeLoop Trace Reporting ---
|
|
1073
1073
|
|
|
1074
|
-
def send_turns_to_cozeloop(turns: List[Dict[str, Any]], session_id: str, history_turns: Optional[List[Dict[str, Any]]] = None, retry_on_auth_failure: bool = True):
|
|
1074
|
+
def send_turns_to_cozeloop(turns: List[Dict[str, Any]], session_id: str, history_turns: Optional[List[Dict[str, Any]]] = None, retry_on_auth_failure: bool = True, coze_tags_override: Optional[Dict[str, str]] = None):
|
|
1075
1075
|
"""Send conversation turns to CozeLoop.
|
|
1076
1076
|
|
|
1077
1077
|
Span hierarchy:
|
|
@@ -1160,6 +1160,11 @@ def send_turns_to_cozeloop(turns: List[Dict[str, Any]], session_id: str, history
|
|
|
1160
1160
|
t = coze_context_tags(um.get("content") if um else None)
|
|
1161
1161
|
if t:
|
|
1162
1162
|
coze_tags = t
|
|
1163
|
+
# 增量上报兜底:本批 turns 不含 <coze-context>(它只在首 turn)时,用 caller
|
|
1164
|
+
# 从 state 传入的 override,保证每个 turn 的 root span 都带 coze_message_id,
|
|
1165
|
+
# 否则后续增量 turn 的 root span 无法按 message_id 查到。
|
|
1166
|
+
if not coze_tags and coze_tags_override:
|
|
1167
|
+
coze_tags = dict(coze_tags_override)
|
|
1163
1168
|
# Drop empty-valued coze_* tags: the backend pairs traces by exact tag
|
|
1164
1169
|
# match (coze_message_id / coze_agent_id), where an empty string is
|
|
1165
1170
|
# indistinguishable from "absent" yet still bloats the span — never
|
|
@@ -1604,7 +1609,7 @@ def send_turns_to_cozeloop(turns: List[Dict[str, Any]], session_id: str, history
|
|
|
1604
1609
|
if new_token:
|
|
1605
1610
|
os.environ["COZELOOP_API_TOKEN"] = new_token
|
|
1606
1611
|
hook_log("retry upload once after forced token refresh")
|
|
1607
|
-
return send_turns_to_cozeloop(turns, session_id, history_turns, retry_on_auth_failure=False)
|
|
1612
|
+
return send_turns_to_cozeloop(turns, session_id, history_turns, retry_on_auth_failure=False, coze_tags_override=coze_tags_override)
|
|
1608
1613
|
return None
|
|
1609
1614
|
|
|
1610
1615
|
return True
|
|
@@ -1733,6 +1738,17 @@ def main():
|
|
|
1733
1738
|
debug_log("No coze-context found in any turn (incl. history), skipping upload.")
|
|
1734
1739
|
return
|
|
1735
1740
|
|
|
1741
|
+
# 持久化 coze_tags 到 state:<coze-context> 只在首 turn,后续增量批次的 turns 不含它,
|
|
1742
|
+
# 其 root span 会缺 coze_message_id 而无法按 message_id 查到。首次解析到就存 state,
|
|
1743
|
+
# 后续批次作为 override 传给 send_turns,保证每个 turn 的 root span 都带 coze_* tag。
|
|
1744
|
+
for _t in list(turns) + list(history_turns):
|
|
1745
|
+
_um = (_t.get("user_message", {}).get("message", {}) or {})
|
|
1746
|
+
_tags = {k: v for k, v in coze_context_tags(_um.get("content")).items() if isinstance(v, str) and v.strip()}
|
|
1747
|
+
if _tags:
|
|
1748
|
+
state["coze_tags"] = _tags
|
|
1749
|
+
break
|
|
1750
|
+
coze_tags_override = state.get("coze_tags") or None
|
|
1751
|
+
|
|
1736
1752
|
# turn 边界控制:中途事件(PostToolUse)触发时,最后一个 turn 往往仍在进行中
|
|
1737
1753
|
# (后续还会追加 step)。若此刻就上报并推进其行号,同一逻辑 turn 会在下次触发时
|
|
1738
1754
|
# 因缺了起始 user 消息而被拆成新的 root span。故中途事件只上报“已完成”的 turn
|
|
@@ -1746,7 +1762,7 @@ def main():
|
|
|
1746
1762
|
return
|
|
1747
1763
|
|
|
1748
1764
|
print(f"[CozeLoop] 开始上报: session={session_id}, event={hook_event}, turns={len(turns_to_send)}/{len(turns)}", file=sys.stderr)
|
|
1749
|
-
uploaded = send_turns_to_cozeloop(turns_to_send, session_id, history_turns)
|
|
1765
|
+
uploaded = send_turns_to_cozeloop(turns_to_send, session_id, history_turns, coze_tags_override=coze_tags_override)
|
|
1750
1766
|
if uploaded is None:
|
|
1751
1767
|
debug_log("Send failed, state not advanced.")
|
|
1752
1768
|
return
|
|
@@ -1077,7 +1077,8 @@ def _make_model_message(role: str, content: str = "", tool_calls: list = None,
|
|
|
1077
1077
|
|
|
1078
1078
|
def send_turns_to_cozeloop(turns: List[Dict[str, Any]], session_id: str, model_name: str = "codex",
|
|
1079
1079
|
history_context: Optional[List[Dict[str, Any]]] = None,
|
|
1080
|
-
retry_on_auth_failure: bool = True
|
|
1080
|
+
retry_on_auth_failure: bool = True,
|
|
1081
|
+
coze_tags_override: Optional[Dict[str, str]] = None) -> Optional[List[Dict[str, Any]]]:
|
|
1081
1082
|
"""Send conversation turns to CozeLoop for tracing.
|
|
1082
1083
|
|
|
1083
1084
|
Span hierarchy:
|
|
@@ -1162,6 +1163,11 @@ def send_turns_to_cozeloop(turns: List[Dict[str, Any]], session_id: str, model_n
|
|
|
1162
1163
|
t = {f"coze_{k}": v for k, v in turn_coze_context(turn).items()}
|
|
1163
1164
|
if t:
|
|
1164
1165
|
coze_tags = t
|
|
1166
|
+
# 增量上报兜底:本批 turns 不含 <coze-context>(它只在首 turn)时,用 caller 从
|
|
1167
|
+
# state 传入的 override,保证每个 turn 的 root span 都带 coze_message_id,否则后续
|
|
1168
|
+
# 增量 turn 的 root span 无法按 message_id 查到。
|
|
1169
|
+
if not coze_tags and coze_tags_override:
|
|
1170
|
+
coze_tags = dict(coze_tags_override)
|
|
1165
1171
|
# Drop empty-valued coze_* tags: the backend pairs traces by exact tag
|
|
1166
1172
|
# match (coze_message_id / coze_agent_id), where an empty string is
|
|
1167
1173
|
# indistinguishable from "absent" yet still bloats the span — never
|
|
@@ -1539,6 +1545,7 @@ def send_turns_to_cozeloop(turns: List[Dict[str, Any]], session_id: str, model_n
|
|
|
1539
1545
|
model_name,
|
|
1540
1546
|
history_context,
|
|
1541
1547
|
retry_on_auth_failure=False,
|
|
1548
|
+
coze_tags_override=coze_tags_override,
|
|
1542
1549
|
)
|
|
1543
1550
|
return None
|
|
1544
1551
|
|
|
@@ -1688,6 +1695,17 @@ def main():
|
|
|
1688
1695
|
if not seen_ctx:
|
|
1689
1696
|
state["seen_coze_context"] = True
|
|
1690
1697
|
|
|
1698
|
+
# 持久化 coze_tags 到 state:<coze-context> 只在首 turn,后续增量批次不含它,其 root span
|
|
1699
|
+
# 会缺 coze_message_id 无法按 message_id 查到。首次解析到就存 state,后续批次作为 override
|
|
1700
|
+
# 传给 send_turns,保证每个 turn 的 root span 都带 coze_* tag。
|
|
1701
|
+
if not state.get("coze_tags"):
|
|
1702
|
+
for _t in turns:
|
|
1703
|
+
_tags = {f"coze_{k}": v for k, v in turn_coze_context(_t).items() if isinstance(v, str) and v.strip()}
|
|
1704
|
+
if _tags:
|
|
1705
|
+
state["coze_tags"] = _tags
|
|
1706
|
+
break
|
|
1707
|
+
coze_tags_override = state.get("coze_tags") or None
|
|
1708
|
+
|
|
1691
1709
|
# 节流:PostToolUse 在密集工具调用下高频触发。距上次上报不足间隔则跳过本次增量上报。
|
|
1692
1710
|
# 终态事件(Stop/SubagentStop)永不被节流,保证 turn 结束时一定收尾。
|
|
1693
1711
|
if not is_terminal_event:
|
|
@@ -1714,6 +1732,7 @@ def main():
|
|
|
1714
1732
|
updated_history = send_turns_to_cozeloop(
|
|
1715
1733
|
turns_to_send, session_id, model_name,
|
|
1716
1734
|
history_context=history_context,
|
|
1735
|
+
coze_tags_override=coze_tags_override,
|
|
1717
1736
|
)
|
|
1718
1737
|
if updated_history is not None:
|
|
1719
1738
|
# 推进 last_processed_line:终态推进到所有 entry 末行;中途保留最后一个未完成 turn,
|