|
1 | 1 | import inspect |
| 2 | +from collections import defaultdict |
2 | 3 | from contextlib import ContextDecorator |
3 | 4 | from contextvars import ContextVar |
4 | 5 | from functools import wraps |
|
11 | 12 | T = TypeVar("T") |
12 | 13 |
|
13 | 14 | _progress_message: ContextVar[Any] = ContextVar("progress_message", default=None) |
| 15 | +_tool_usage_counts: ContextVar[dict[str, int] | None] = ContextVar( |
| 16 | + "tool_usage_counts", default=None |
| 17 | +) |
| 18 | +_current_tool: ContextVar[str | None] = ContextVar("current_tool", default=None) |
14 | 19 |
|
15 | 20 |
|
16 | 21 | class DecorateMethodContext(ContextDecorator): |
@@ -77,18 +82,44 @@ async def wrapper(*args, **kwargs) -> T: |
77 | 82 | ): |
78 | 83 | tool_name = args[0].function.__name__ |
79 | 84 |
|
| 85 | + # Update tool usage counts |
| 86 | + counts = _tool_usage_counts.get() |
| 87 | + if counts is None: |
| 88 | + counts = defaultdict(int) |
| 89 | + _tool_usage_counts.set(counts) |
| 90 | + counts[tool_name] += 1 |
| 91 | + |
| 92 | + # Set current tool |
| 93 | + _current_tool_token = _current_tool.set(tool_name) |
| 94 | + |
80 | 95 | try: |
81 | | - await _progress.append(f"🔧 {tool_name}") |
| 96 | + # Build the progress message with better formatting |
| 97 | + lines = [] |
| 98 | + lines.append(f"🔧 Using: `{tool_name}`") |
| 99 | + lines.append("") # Empty line for spacing |
| 100 | + |
| 101 | + # Build summary of all tools used |
| 102 | + if counts: |
| 103 | + lines.append("📊 Tools used:") |
| 104 | + for tool, count in sorted(counts.items()): |
| 105 | + lines.append(f" • `{tool}` ({count}x)") |
| 106 | + |
| 107 | + full_message = "\n".join(lines) |
| 108 | + await _progress.update(full_message) |
82 | 109 | except Exception: |
83 | 110 | pass |
84 | 111 |
|
85 | | - wrapped_callable = decorator(**settings or {})(func) |
86 | | - with prefect_tags(*tags): |
87 | | - result = wrapped_callable(*args, **kwargs) # type: ignore |
88 | | - if inspect.isawaitable(result): |
89 | | - result = await result |
90 | | - |
91 | | - return result |
| 112 | + try: |
| 113 | + wrapped_callable = decorator(**settings or {})(func) |
| 114 | + with prefect_tags(*tags): |
| 115 | + result = wrapped_callable(*args, **kwargs) # type: ignore |
| 116 | + if inspect.isawaitable(result): |
| 117 | + result = await result |
| 118 | + |
| 119 | + return result |
| 120 | + finally: |
| 121 | + if _progress: |
| 122 | + _current_tool.reset(_current_tool_token) |
92 | 123 |
|
93 | 124 | return wrapper # type: ignore |
94 | 125 |
|
|
0 commit comments