|
2 | 2 | # coding: utf-8 |
3 | 3 |
|
4 | 4 | import os |
| 5 | +import httpx |
| 6 | +import pickle |
| 7 | +import yaml |
| 8 | +import logging |
| 9 | +from pathlib import Path |
| 10 | +from typing import Union, List, Any, Optional |
| 11 | +import json |
| 12 | +from importlib.resources import files, as_file |
| 13 | +from pydantic_ai.models.openai import OpenAIChatModel |
| 14 | +from pydantic_ai.models.google import GoogleModel |
| 15 | +from pydantic_ai.models.huggingface import HuggingFaceModel |
| 16 | +from pydantic_ai.models.groq import GroqModel |
| 17 | +from pydantic_ai.models.mistral import MistralModel |
| 18 | +from fasta2a import Skill |
5 | 19 |
|
6 | 20 | try: |
7 | | - |
8 | 21 | from openai import AsyncOpenAI |
9 | 22 | from pydantic_ai.providers.openai import OpenAIProvider |
10 | 23 | except ImportError: |
|
26 | 39 | MistralProvider = None |
27 | 40 |
|
28 | 41 | try: |
| 42 | + from pydantic_ai.models.anthropic import AnthropicModel |
29 | 43 | from anthropic import AsyncAnthropic |
30 | 44 | from pydantic_ai.providers.anthropic import AnthropicProvider |
31 | 45 | except ImportError: |
| 46 | + AnthropicModel = None |
32 | 47 | AsyncAnthropic = None |
33 | 48 | AnthropicProvider = None |
34 | 49 |
|
35 | | -import httpx |
36 | | -import pickle |
37 | | -import yaml |
38 | | -from pathlib import Path |
39 | | -from typing import Any, Union, List, Optional |
40 | | -import json |
41 | | -from importlib.resources import files, as_file |
42 | | -from pydantic_ai.models.openai import OpenAIChatModel |
43 | | -from pydantic_ai.models.anthropic import AnthropicModel |
44 | | -from pydantic_ai.models.google import GoogleModel |
45 | | -from pydantic_ai.models.huggingface import HuggingFaceModel |
46 | | -from pydantic_ai.models.groq import GroqModel |
47 | | -from pydantic_ai.models.mistral import MistralModel |
48 | | -from pydantic_ai_skills import Skill |
| 50 | + |
| 51 | +logger = logging.getLogger(__name__) |
49 | 52 |
|
50 | 53 |
|
51 | 54 | def to_integer(string: Union[str, int] = None) -> int: |
@@ -163,6 +166,9 @@ def load_model(file: str) -> Any: |
163 | 166 | def retrieve_package_name() -> str: |
164 | 167 | """ |
165 | 168 | Returns the top-level package name of the module that imported this utils.py. |
| 169 | +
|
| 170 | + Works reliably when utils.py is inside a proper package (with __init__.py or |
| 171 | + implicit namespace package) and the caller does normal imports. |
166 | 172 | """ |
167 | 173 | if __package__: |
168 | 174 | top = __package__.partition(".")[0] |
@@ -363,6 +369,16 @@ def create_model( |
363 | 369 | def extract_tool_tags(tool_def: Any) -> List[str]: |
364 | 370 | """ |
365 | 371 | Extracts tags from a tool definition object. |
| 372 | +
|
| 373 | + Found structure in debug: |
| 374 | + tool_def.name (str) |
| 375 | + tool_def.meta (dict) -> {'fastmcp': {'tags': ['tag']}} |
| 376 | +
|
| 377 | + This function checks multiple paths to be robust: |
| 378 | + 1. tool_def.meta['fastmcp']['tags'] |
| 379 | + 2. tool_def.meta['tags'] |
| 380 | + 3. tool_def.metadata['tags'] (legacy/alternative wrapper) |
| 381 | + 4. tool_def.metadata.get('meta')... (nested path) |
366 | 382 | """ |
367 | 383 | tags_list = [] |
368 | 384 |
|
@@ -409,3 +425,10 @@ def tool_in_tag(tool_def: Any, tag: str) -> bool: |
409 | 425 | return True |
410 | 426 | else: |
411 | 427 | return False |
| 428 | + |
| 429 | + |
| 430 | +def filter_tools_by_tag(tools: List[Any], tag: str) -> List[Any]: |
| 431 | + """ |
| 432 | + Filters a list of tools for a given tag. |
| 433 | + """ |
| 434 | + return [t for t in tools if tool_in_tag(t, tag)] |
0 commit comments