| 119 | |
| 120 | |
| 121 | def build_tool( |
| 122 | *, |
| 123 | name: str, |
| 124 | input_schema: Mapping[str, Any], |
| 125 | call: Callable[[dict[str, Any], ToolContext], ToolResult], |
| 126 | prompt: Callable[..., str] | str | None = None, |
| 127 | description: Callable[[dict[str, Any]], str] | str | None = None, |
| 128 | map_result_to_api: Callable[[Any, str], dict[str, Any]] | None = None, |
| 129 | aliases: tuple[str, ...] | list[str] = (), |
| 130 | search_hint: str | None = None, |
| 131 | max_result_size_chars: int | float = 20_000, |
| 132 | strict: bool = False, |
| 133 | should_defer: bool = False, |
| 134 | always_load: bool = False, |
| 135 | is_mcp: bool = False, |
| 136 | is_lsp: bool = False, |
| 137 | is_enabled: Callable[[], bool] | None = None, |
| 138 | is_concurrency_safe: Callable[[dict[str, Any]], bool] | None = None, |
| 139 | is_read_only: Callable[[dict[str, Any]], bool] | None = None, |
| 140 | is_destructive: Callable[[dict[str, Any]], bool] | None = None, |
| 141 | check_permissions: Callable[[dict[str, Any], ToolContext], PermissionResult] | None = None, |
| 142 | validate_input: Callable[[dict[str, Any], ToolContext], ValidationResult] | None = None, |
| 143 | user_facing_name: Callable[[dict[str, Any] | None], str] | None = None, |
| 144 | get_path: Callable[[dict[str, Any]], str] | None = None, |
| 145 | to_auto_classifier_input: Callable[[dict[str, Any]], Any] | None = None, |
| 146 | input_json_schema: Mapping[str, Any] | None = None, |
| 147 | mcp_info: McpInfo | None = None, |
| 148 | interrupt_behavior: Callable[[], Literal["cancel", "block"]] | None = None, |
| 149 | is_search_or_read_command: Callable[[dict[str, Any]], SearchOrReadResult] | None = None, |
| 150 | is_open_world: Callable[[dict[str, Any]], bool] | None = None, |
| 151 | requires_user_interaction: Callable[[], bool] | None = None, |
| 152 | inputs_equivalent: Callable[[dict[str, Any], dict[str, Any]], bool] | None = None, |
| 153 | backfill_observable_input: Callable[[dict[str, Any]], None] | None = None, |
| 154 | prepare_permission_matcher: Callable[[dict[str, Any]], Callable[[str], bool]] | None = None, |
| 155 | get_tool_use_summary: Callable[[dict[str, Any] | None], str | None] | None = None, |
| 156 | get_activity_description: Callable[[dict[str, Any] | None], str | None] | None = None, |
| 157 | ) -> Tool: |
| 158 | if isinstance(prompt, str): |
| 159 | _p = prompt |
| 160 | prompt_fn: Callable[..., str] = lambda: _p |
| 161 | elif prompt is None: |
| 162 | prompt_fn = lambda: "" |
| 163 | else: |
| 164 | prompt_fn = prompt |
| 165 | |
| 166 | if isinstance(description, str): |
| 167 | _d = description |
| 168 | desc_fn: Callable[[dict[str, Any]], str] = lambda _input: _d |
| 169 | elif description is None: |
| 170 | desc_fn = lambda _input: name |
| 171 | else: |
| 172 | desc_fn = description |
| 173 | |
| 174 | return Tool( |
| 175 | name=name, |
| 176 | input_schema=input_schema, |
| 177 | call=call, |
| 178 | prompt=prompt_fn, |