mcp-proxy-adapter 3.0.0__py3-none-any.whl → 3.0.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.
- examples/basic_example/README.md +123 -9
- examples/basic_example/config.json +4 -0
- examples/basic_example/docs/EN/README.md +46 -5
- examples/basic_example/docs/RU/README.md +46 -5
- examples/basic_example/server.py +127 -21
- examples/complete_example/commands/system_command.py +1 -0
- examples/complete_example/server.py +65 -11
- examples/minimal_example/README.md +20 -6
- examples/minimal_example/config.json +7 -14
- examples/minimal_example/main.py +109 -40
- examples/minimal_example/simple_server.py +53 -14
- examples/minimal_example/tests/conftest.py +1 -1
- examples/minimal_example/tests/test_integration.py +8 -10
- examples/simple_server.py +12 -21
- examples/test_server.py +22 -14
- examples/tool_description_example.py +82 -0
- mcp_proxy_adapter/api/__init__.py +0 -0
- mcp_proxy_adapter/api/app.py +391 -0
- mcp_proxy_adapter/api/handlers.py +229 -0
- mcp_proxy_adapter/api/middleware/__init__.py +49 -0
- mcp_proxy_adapter/api/middleware/auth.py +146 -0
- mcp_proxy_adapter/api/middleware/base.py +79 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +198 -0
- mcp_proxy_adapter/api/middleware/logging.py +96 -0
- mcp_proxy_adapter/api/middleware/performance.py +83 -0
- mcp_proxy_adapter/api/middleware/rate_limit.py +152 -0
- mcp_proxy_adapter/api/schemas.py +305 -0
- mcp_proxy_adapter/api/tool_integration.py +223 -0
- mcp_proxy_adapter/api/tools.py +198 -0
- mcp_proxy_adapter/commands/__init__.py +19 -0
- mcp_proxy_adapter/commands/base.py +301 -0
- mcp_proxy_adapter/commands/command_registry.py +231 -0
- mcp_proxy_adapter/commands/config_command.py +113 -0
- mcp_proxy_adapter/commands/health_command.py +136 -0
- mcp_proxy_adapter/commands/help_command.py +193 -0
- mcp_proxy_adapter/commands/result.py +215 -0
- mcp_proxy_adapter/config.py +9 -0
- mcp_proxy_adapter/core/__init__.py +0 -0
- mcp_proxy_adapter/core/errors.py +173 -0
- mcp_proxy_adapter/core/logging.py +205 -0
- mcp_proxy_adapter/core/utils.py +138 -0
- mcp_proxy_adapter/py.typed +0 -0
- mcp_proxy_adapter/schemas/base_schema.json +114 -0
- mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +3 -0
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +115 -0
- mcp_proxy_adapter/tests/api/test_middleware.py +336 -0
- mcp_proxy_adapter/tests/commands/__init__.py +3 -0
- mcp_proxy_adapter/tests/commands/test_config_command.py +211 -0
- mcp_proxy_adapter/tests/commands/test_echo_command.py +127 -0
- mcp_proxy_adapter/tests/commands/test_help_command.py +133 -0
- mcp_proxy_adapter/tests/conftest.py +131 -0
- mcp_proxy_adapter/tests/functional/__init__.py +3 -0
- mcp_proxy_adapter/tests/functional/test_api.py +235 -0
- mcp_proxy_adapter/tests/integration/__init__.py +3 -0
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +130 -0
- mcp_proxy_adapter/tests/integration/test_integration.py +255 -0
- mcp_proxy_adapter/tests/performance/__init__.py +3 -0
- mcp_proxy_adapter/tests/performance/test_performance.py +189 -0
- mcp_proxy_adapter/tests/stubs/__init__.py +10 -0
- mcp_proxy_adapter/tests/stubs/echo_command.py +104 -0
- mcp_proxy_adapter/tests/test_api_endpoints.py +271 -0
- mcp_proxy_adapter/tests/test_api_handlers.py +289 -0
- mcp_proxy_adapter/tests/test_base_command.py +123 -0
- mcp_proxy_adapter/tests/test_batch_requests.py +117 -0
- mcp_proxy_adapter/tests/test_command_registry.py +245 -0
- mcp_proxy_adapter/tests/test_config.py +127 -0
- mcp_proxy_adapter/tests/test_utils.py +65 -0
- mcp_proxy_adapter/tests/unit/__init__.py +3 -0
- mcp_proxy_adapter/tests/unit/test_base_command.py +130 -0
- mcp_proxy_adapter/tests/unit/test_config.py +217 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-3.0.1.dist-info/RECORD +109 -0
- examples/basic_example/config.yaml +0 -20
- examples/basic_example/main.py +0 -50
- examples/complete_example/main.py +0 -67
- examples/minimal_example/config.yaml +0 -26
- mcp_proxy_adapter/framework.py +0 -109
- mcp_proxy_adapter-3.0.0.dist-info/RECORD +0 -58
- {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-3.0.0.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,198 @@
|
|
1
|
+
"""
|
2
|
+
Модуль с реализацией инструментов API для внешних систем.
|
3
|
+
|
4
|
+
Этот модуль содержит классы инструментов API, которые могут быть
|
5
|
+
интегрированы с внешними системами для выполнения команд микросервиса.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import Any, Dict, Optional, Union, List
|
9
|
+
import json
|
10
|
+
import logging
|
11
|
+
|
12
|
+
from mcp_proxy_adapter.api.tool_integration import ToolIntegration
|
13
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
14
|
+
from mcp_proxy_adapter.core.errors import NotFoundError, InvalidParamsError
|
15
|
+
|
16
|
+
logger = logging.getLogger(__name__)
|
17
|
+
|
18
|
+
|
19
|
+
class TSTCommandExecutor:
|
20
|
+
"""
|
21
|
+
Инструмент для выполнения команд через JSON-RPC протокол на сервере проекта.
|
22
|
+
|
23
|
+
Этот класс предоставляет функциональность для выполнения команд микросервиса
|
24
|
+
через внешний интерфейс TST (Tool-System-Transport).
|
25
|
+
"""
|
26
|
+
|
27
|
+
name = "tst_execute_command"
|
28
|
+
description = "Выполняет команду через JSON-RPC протокол."
|
29
|
+
|
30
|
+
@classmethod
|
31
|
+
async def execute(cls, command: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
32
|
+
"""
|
33
|
+
Выполняет команду с указанными параметрами.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
command: Имя команды для выполнения
|
37
|
+
params: Параметры команды (опционально)
|
38
|
+
|
39
|
+
Returns:
|
40
|
+
Результат выполнения команды
|
41
|
+
|
42
|
+
Raises:
|
43
|
+
NotFoundError: Если команда не найдена
|
44
|
+
InvalidParamsError: Если переданы некорректные параметры
|
45
|
+
"""
|
46
|
+
if not params:
|
47
|
+
params = {}
|
48
|
+
|
49
|
+
logger.info(f"Executing command via TST: {command}, params: {params}")
|
50
|
+
|
51
|
+
try:
|
52
|
+
# Проверяем существование команды
|
53
|
+
if not registry.command_exists(command):
|
54
|
+
raise NotFoundError(f"Команда '{command}' не найдена")
|
55
|
+
|
56
|
+
# Получаем класс команды
|
57
|
+
command_class = registry.get_command(command)
|
58
|
+
|
59
|
+
# Выполняем команду
|
60
|
+
result = await command_class.run(**params)
|
61
|
+
|
62
|
+
# Возвращаем результат
|
63
|
+
return result.to_dict()
|
64
|
+
except NotFoundError as e:
|
65
|
+
logger.error(f"Command not found: {command}")
|
66
|
+
raise
|
67
|
+
except Exception as e:
|
68
|
+
logger.exception(f"Error executing command {command}: {e}")
|
69
|
+
raise
|
70
|
+
|
71
|
+
@classmethod
|
72
|
+
def get_schema(cls) -> Dict[str, Any]:
|
73
|
+
"""
|
74
|
+
Возвращает схему инструмента в формате OpenAPI.
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
Словарь со схемой инструмента
|
78
|
+
"""
|
79
|
+
return ToolIntegration.generate_tool_schema(cls.name, registry, cls.description)
|
80
|
+
|
81
|
+
@classmethod
|
82
|
+
def get_description(cls, format: str = "json") -> Union[Dict[str, Any], str]:
|
83
|
+
"""
|
84
|
+
Возвращает полное описание инструмента в указанном формате.
|
85
|
+
|
86
|
+
Args:
|
87
|
+
format: Формат описания (json, markdown, html)
|
88
|
+
|
89
|
+
Returns:
|
90
|
+
Описание инструмента в указанном формате
|
91
|
+
"""
|
92
|
+
if format.lower() == "json":
|
93
|
+
# Получаем базовое описание инструмента
|
94
|
+
base_description = ToolIntegration.generate_tool_schema(cls.name, registry, cls.description)
|
95
|
+
|
96
|
+
# Добавляем дополнительную информацию
|
97
|
+
base_description["examples"] = cls._generate_examples()
|
98
|
+
base_description["error_codes"] = cls._generate_error_codes()
|
99
|
+
|
100
|
+
return base_description
|
101
|
+
elif format.lower() in ["markdown", "text", "html"]:
|
102
|
+
return ToolIntegration.generate_tool_documentation(cls.name, registry, format)
|
103
|
+
else:
|
104
|
+
# По умолчанию возвращаем JSON формат
|
105
|
+
return ToolIntegration.generate_tool_schema(cls.name, registry, cls.description)
|
106
|
+
|
107
|
+
@classmethod
|
108
|
+
def _generate_examples(cls) -> List[Dict[str, Any]]:
|
109
|
+
"""
|
110
|
+
Генерирует примеры использования инструмента.
|
111
|
+
|
112
|
+
Returns:
|
113
|
+
Список примеров использования
|
114
|
+
"""
|
115
|
+
examples = []
|
116
|
+
|
117
|
+
# Получаем метаданные всех команд
|
118
|
+
all_metadata = registry.get_all_metadata()
|
119
|
+
|
120
|
+
# Добавляем по одному примеру для каждой команды
|
121
|
+
for cmd_name, metadata in all_metadata.items():
|
122
|
+
if metadata.get("examples"):
|
123
|
+
# Берем первый пример из метаданных
|
124
|
+
example = metadata["examples"][0]
|
125
|
+
|
126
|
+
# Формируем пример использования инструмента
|
127
|
+
examples.append({
|
128
|
+
"command": cls.name,
|
129
|
+
"params": {
|
130
|
+
"command": example.get("command", cmd_name),
|
131
|
+
"params": example.get("params", {})
|
132
|
+
},
|
133
|
+
"description": f"Выполнение команды {cmd_name}"
|
134
|
+
})
|
135
|
+
|
136
|
+
return examples
|
137
|
+
|
138
|
+
@classmethod
|
139
|
+
def _generate_error_codes(cls) -> Dict[str, str]:
|
140
|
+
"""
|
141
|
+
Генерирует словарь возможных кодов ошибок.
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
Словарь с кодами ошибок и их описаниями
|
145
|
+
"""
|
146
|
+
return {
|
147
|
+
"-32600": "Некорректный запрос",
|
148
|
+
"-32601": "Команда не найдена",
|
149
|
+
"-32602": "Некорректные параметры",
|
150
|
+
"-32603": "Внутренняя ошибка",
|
151
|
+
"-32000": "Ошибка выполнения команды"
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
# Экспортируем доступные инструменты API
|
156
|
+
available_tools = {
|
157
|
+
TSTCommandExecutor.name: TSTCommandExecutor
|
158
|
+
}
|
159
|
+
|
160
|
+
|
161
|
+
def get_tool_description(tool_name: str, format: str = "json") -> Union[Dict[str, Any], str]:
|
162
|
+
"""
|
163
|
+
Получает описание инструмента API по имени.
|
164
|
+
|
165
|
+
Args:
|
166
|
+
tool_name: Имя инструмента API
|
167
|
+
format: Формат описания (json, markdown, html)
|
168
|
+
|
169
|
+
Returns:
|
170
|
+
Описание инструмента в указанном формате
|
171
|
+
|
172
|
+
Raises:
|
173
|
+
NotFoundError: Если инструмент не найден
|
174
|
+
"""
|
175
|
+
if tool_name in available_tools:
|
176
|
+
return available_tools[tool_name].get_description(format)
|
177
|
+
else:
|
178
|
+
raise NotFoundError(f"Инструмент '{tool_name}' не найден")
|
179
|
+
|
180
|
+
|
181
|
+
async def execute_tool(tool_name: str, **params) -> Dict[str, Any]:
|
182
|
+
"""
|
183
|
+
Выполняет инструмент API с указанными параметрами.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
tool_name: Имя инструмента API
|
187
|
+
**params: Параметры инструмента
|
188
|
+
|
189
|
+
Returns:
|
190
|
+
Результат выполнения инструмента
|
191
|
+
|
192
|
+
Raises:
|
193
|
+
NotFoundError: Если инструмент не найден
|
194
|
+
"""
|
195
|
+
if tool_name in available_tools:
|
196
|
+
return await available_tools[tool_name].execute(**params)
|
197
|
+
else:
|
198
|
+
raise NotFoundError(f"Инструмент '{tool_name}' не найден")
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"""
|
2
|
+
Package with command implementation.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from mcp_proxy_adapter.commands.base import Command
|
6
|
+
from mcp_proxy_adapter.commands.result import CommandResult, SuccessResult, ErrorResult
|
7
|
+
from mcp_proxy_adapter.commands.command_registry import registry, CommandRegistry
|
8
|
+
|
9
|
+
# Automatically discover and register commands
|
10
|
+
registry.discover_commands()
|
11
|
+
|
12
|
+
__all__ = [
|
13
|
+
"Command",
|
14
|
+
"CommandResult",
|
15
|
+
"SuccessResult",
|
16
|
+
"ErrorResult",
|
17
|
+
"registry",
|
18
|
+
"CommandRegistry"
|
19
|
+
]
|
@@ -0,0 +1,301 @@
|
|
1
|
+
"""
|
2
|
+
Module with base command class.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import inspect
|
6
|
+
from abc import ABC, abstractmethod
|
7
|
+
from typing import Any, ClassVar, Dict, List, Optional, Type, TypeVar, Union
|
8
|
+
|
9
|
+
from mcp_proxy_adapter.commands.result import CommandResult, ErrorResult, SuccessResult
|
10
|
+
from mcp_proxy_adapter.core.errors import (
|
11
|
+
ValidationError, CommandError, InternalError, InvalidParamsError,
|
12
|
+
NotFoundError, TimeoutError
|
13
|
+
)
|
14
|
+
from mcp_proxy_adapter.core.logging import logger
|
15
|
+
|
16
|
+
T = TypeVar("T", bound=CommandResult)
|
17
|
+
|
18
|
+
|
19
|
+
class Command(ABC):
|
20
|
+
"""
|
21
|
+
Base abstract class for all commands.
|
22
|
+
"""
|
23
|
+
|
24
|
+
# Command name for registration
|
25
|
+
name: ClassVar[str]
|
26
|
+
# Result class
|
27
|
+
result_class: ClassVar[Type[CommandResult]]
|
28
|
+
|
29
|
+
@abstractmethod
|
30
|
+
async def execute(self, **kwargs) -> CommandResult:
|
31
|
+
"""
|
32
|
+
Executes command with given parameters.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
**kwargs: Command parameters.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
Command execution result.
|
39
|
+
"""
|
40
|
+
pass
|
41
|
+
|
42
|
+
@classmethod
|
43
|
+
def get_schema(cls) -> Dict[str, Any]:
|
44
|
+
"""
|
45
|
+
Returns JSON schema for command parameters validation.
|
46
|
+
This method should be overridden in child classes.
|
47
|
+
|
48
|
+
Returns:
|
49
|
+
Dictionary with JSON schema.
|
50
|
+
"""
|
51
|
+
# Default base schema that can be overridden
|
52
|
+
return {
|
53
|
+
"type": "object",
|
54
|
+
"properties": {},
|
55
|
+
"additionalProperties": False
|
56
|
+
}
|
57
|
+
|
58
|
+
@classmethod
|
59
|
+
def get_result_schema(cls) -> Dict[str, Any]:
|
60
|
+
"""
|
61
|
+
Returns JSON schema for command result validation.
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
Dictionary with JSON schema.
|
65
|
+
"""
|
66
|
+
if hasattr(cls, "result_class") and cls.result_class:
|
67
|
+
return cls.result_class.get_schema()
|
68
|
+
return {}
|
69
|
+
|
70
|
+
@classmethod
|
71
|
+
def validate_params(cls, params: Dict[str, Any]) -> Dict[str, Any]:
|
72
|
+
"""
|
73
|
+
Validates command parameters before execution.
|
74
|
+
This method can be overridden in child classes for custom validation.
|
75
|
+
|
76
|
+
Args:
|
77
|
+
params: Parameters to validate.
|
78
|
+
|
79
|
+
Returns:
|
80
|
+
Validated parameters.
|
81
|
+
|
82
|
+
Raises:
|
83
|
+
ValidationError: If parameters failed validation.
|
84
|
+
"""
|
85
|
+
# In base implementation, simply return parameters without validation
|
86
|
+
# In real implementation, jsonschema or pydantic will be used here
|
87
|
+
return params
|
88
|
+
|
89
|
+
@classmethod
|
90
|
+
async def run(cls, **kwargs) -> CommandResult:
|
91
|
+
"""
|
92
|
+
Runs command with parameters validation.
|
93
|
+
|
94
|
+
Args:
|
95
|
+
**kwargs: Command parameters.
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
Command execution result.
|
99
|
+
"""
|
100
|
+
try:
|
101
|
+
logger.debug(f"Running command {cls.__name__} with params: {kwargs}")
|
102
|
+
|
103
|
+
# Parameters validation
|
104
|
+
validated_params = cls.validate_params(kwargs)
|
105
|
+
|
106
|
+
# Create command instance
|
107
|
+
command = cls()
|
108
|
+
|
109
|
+
# Execute command
|
110
|
+
result = await command.execute(**validated_params)
|
111
|
+
|
112
|
+
logger.debug(f"Command {cls.__name__} executed successfully")
|
113
|
+
return result
|
114
|
+
except ValidationError as e:
|
115
|
+
# Ошибка валидации параметров
|
116
|
+
logger.error(f"Validation error in command {cls.__name__}: {e}")
|
117
|
+
return ErrorResult(
|
118
|
+
message=str(e),
|
119
|
+
code=e.code,
|
120
|
+
details=e.data
|
121
|
+
)
|
122
|
+
except InvalidParamsError as e:
|
123
|
+
# Ошибка в параметрах команды
|
124
|
+
logger.error(f"Invalid parameters error in command {cls.__name__}: {e}")
|
125
|
+
return ErrorResult(
|
126
|
+
message=str(e),
|
127
|
+
code=e.code,
|
128
|
+
details=e.data
|
129
|
+
)
|
130
|
+
except NotFoundError as e:
|
131
|
+
# Ресурс не найден
|
132
|
+
logger.error(f"Resource not found error in command {cls.__name__}: {e}")
|
133
|
+
return ErrorResult(
|
134
|
+
message=str(e),
|
135
|
+
code=e.code,
|
136
|
+
details=e.data
|
137
|
+
)
|
138
|
+
except TimeoutError as e:
|
139
|
+
# Превышено время ожидания
|
140
|
+
logger.error(f"Timeout error in command {cls.__name__}: {e}")
|
141
|
+
return ErrorResult(
|
142
|
+
message=str(e),
|
143
|
+
code=e.code,
|
144
|
+
details=e.data
|
145
|
+
)
|
146
|
+
except CommandError as e:
|
147
|
+
# Ошибка выполнения команды
|
148
|
+
logger.error(f"Command error in {cls.__name__}: {e}")
|
149
|
+
return ErrorResult(
|
150
|
+
message=str(e),
|
151
|
+
code=e.code,
|
152
|
+
details=e.data
|
153
|
+
)
|
154
|
+
except Exception as e:
|
155
|
+
# Непредвиденная ошибка
|
156
|
+
logger.exception(f"Unexpected error executing command {cls.__name__}: {e}")
|
157
|
+
internal_error = InternalError(f"Command execution error: {str(e)}")
|
158
|
+
return ErrorResult(
|
159
|
+
message=internal_error.message,
|
160
|
+
code=internal_error.code,
|
161
|
+
details={"original_error": str(e)}
|
162
|
+
)
|
163
|
+
|
164
|
+
@classmethod
|
165
|
+
def get_param_info(cls) -> Dict[str, Dict[str, Any]]:
|
166
|
+
"""
|
167
|
+
Gets information about execute method parameters.
|
168
|
+
|
169
|
+
Returns:
|
170
|
+
Dictionary with parameters information.
|
171
|
+
"""
|
172
|
+
signature = inspect.signature(cls.execute)
|
173
|
+
params = {}
|
174
|
+
|
175
|
+
for name, param in signature.parameters.items():
|
176
|
+
if name == "self":
|
177
|
+
continue
|
178
|
+
|
179
|
+
param_info = {
|
180
|
+
"name": name,
|
181
|
+
"required": param.default == inspect.Parameter.empty
|
182
|
+
}
|
183
|
+
|
184
|
+
if param.annotation != inspect.Parameter.empty:
|
185
|
+
param_info["type"] = str(param.annotation)
|
186
|
+
|
187
|
+
if param.default != inspect.Parameter.empty:
|
188
|
+
param_info["default"] = param.default
|
189
|
+
|
190
|
+
params[name] = param_info
|
191
|
+
|
192
|
+
return params
|
193
|
+
|
194
|
+
@classmethod
|
195
|
+
def get_metadata(cls) -> Dict[str, Any]:
|
196
|
+
"""
|
197
|
+
Returns complete metadata about the command.
|
198
|
+
|
199
|
+
Provides a single access point to all command metadata.
|
200
|
+
|
201
|
+
Returns:
|
202
|
+
Dict with command metadata
|
203
|
+
"""
|
204
|
+
# Get and format docstring
|
205
|
+
doc = cls.__doc__ or ""
|
206
|
+
description = inspect.cleandoc(doc) if doc else ""
|
207
|
+
|
208
|
+
# Extract first line for summary
|
209
|
+
summary = description.split("\n")[0] if description else ""
|
210
|
+
|
211
|
+
# Get parameters information
|
212
|
+
param_info = cls.get_param_info()
|
213
|
+
|
214
|
+
# Generate examples based on parameters
|
215
|
+
examples = cls._generate_examples(param_info)
|
216
|
+
|
217
|
+
return {
|
218
|
+
"name": cls.name,
|
219
|
+
"summary": summary,
|
220
|
+
"description": description,
|
221
|
+
"params": param_info,
|
222
|
+
"examples": examples,
|
223
|
+
"schema": cls.get_schema(),
|
224
|
+
"result_schema": cls.get_result_schema(),
|
225
|
+
"result_class": cls.result_class.__name__ if hasattr(cls, "result_class") else None,
|
226
|
+
}
|
227
|
+
|
228
|
+
@classmethod
|
229
|
+
def _generate_examples(cls, params: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
|
230
|
+
"""
|
231
|
+
Generates usage examples of the command based on its parameters.
|
232
|
+
|
233
|
+
Args:
|
234
|
+
params: Information about command parameters
|
235
|
+
|
236
|
+
Returns:
|
237
|
+
List of examples
|
238
|
+
"""
|
239
|
+
examples = []
|
240
|
+
|
241
|
+
# Simple example without parameters, if all parameters are optional
|
242
|
+
if not any(param.get("required", False) for param in params.values()):
|
243
|
+
examples.append({
|
244
|
+
"command": cls.name,
|
245
|
+
"description": f"Call {cls.name} command without parameters"
|
246
|
+
})
|
247
|
+
|
248
|
+
# Example with all required parameters
|
249
|
+
required_params = {k: v for k, v in params.items() if v.get("required", False)}
|
250
|
+
if required_params:
|
251
|
+
example_params = {}
|
252
|
+
for param_name, param_info in required_params.items():
|
253
|
+
# Generate suitable example value based on parameter type
|
254
|
+
param_type = param_info.get("type", "")
|
255
|
+
if "str" in param_type.lower():
|
256
|
+
example_params[param_name] = f"example_{param_name}"
|
257
|
+
elif "int" in param_type.lower():
|
258
|
+
example_params[param_name] = 123
|
259
|
+
elif "float" in param_type.lower():
|
260
|
+
example_params[param_name] = 123.45
|
261
|
+
elif "bool" in param_type.lower():
|
262
|
+
example_params[param_name] = True
|
263
|
+
else:
|
264
|
+
example_params[param_name] = f"value_for_{param_name}"
|
265
|
+
|
266
|
+
examples.append({
|
267
|
+
"command": cls.name,
|
268
|
+
"params": example_params,
|
269
|
+
"description": f"Call {cls.name} command with required parameters"
|
270
|
+
})
|
271
|
+
|
272
|
+
# Add example with all parameters, if there are optional ones
|
273
|
+
optional_params = {k: v for k, v in params.items() if not v.get("required", False)}
|
274
|
+
if optional_params and required_params:
|
275
|
+
full_example_params = dict(example_params) if 'example_params' in locals() else {}
|
276
|
+
|
277
|
+
for param_name, param_info in optional_params.items():
|
278
|
+
# Get default value or generate suitable example
|
279
|
+
if "default" in param_info:
|
280
|
+
full_example_params[param_name] = param_info["default"]
|
281
|
+
else:
|
282
|
+
# Generate suitable example value based on parameter type
|
283
|
+
param_type = param_info.get("type", "")
|
284
|
+
if "str" in param_type.lower():
|
285
|
+
full_example_params[param_name] = f"optional_{param_name}"
|
286
|
+
elif "int" in param_type.lower():
|
287
|
+
full_example_params[param_name] = 456
|
288
|
+
elif "float" in param_type.lower():
|
289
|
+
full_example_params[param_name] = 45.67
|
290
|
+
elif "bool" in param_type.lower():
|
291
|
+
full_example_params[param_name] = False
|
292
|
+
else:
|
293
|
+
full_example_params[param_name] = f"optional_value_for_{param_name}"
|
294
|
+
|
295
|
+
examples.append({
|
296
|
+
"command": cls.name,
|
297
|
+
"params": full_example_params,
|
298
|
+
"description": f"Call {cls.name} command with all parameters"
|
299
|
+
})
|
300
|
+
|
301
|
+
return examples
|