Repository: ErikBjare/gptme
File: gptme/tools/__init__.py (Python)

Code before:
                allowlist = env_allowlist.split(",")
            elif config.chat and config.chat.tools:
                allowlist = config.chat.tools

        for tool in get_toolchain(allowlist):
            if tool in loaded_tools:
                # logger.warning("Tool '%s' already loaded", tool.name)
                continue
            if tool.init:
                tool = tool.init()

            loaded_tools.append(tool)

        for tool_name in allowlist or []:
            if not has_tool(tool_name):
                # if the tool is found but unavailable, we log a warning
                if tool_name in [tool.name for tool in get_available_tools()]:
                    logger.warning("Tool %s found but is unavailable", tool_name)
                    continue
                raise ValueError(f"Tool '{tool_name}' not found")

        return loaded_tools


def get_toolchain(allowlist: list[str] | None) -> list[ToolSpec]:
    # Validate allowlist if provided
    if allowlist is not None:
        available_tools = get_available_tools()
        available_tool_names = [tool.name for tool in available_tools]

        for tool_name in allowlist:
            if tool_name not in available_tool_names:
                raise ValueError(
                    f"Tool '{tool_name}' not found. Available tools: {', '.join(sorted(available_tool_names))}"
                )

            # Check if tool is available
            tool_obj = next(tool for tool in available_tools if tool.name == tool_name)
            if not tool_obj.is_available:
                raise ValueError(
                    f"Tool '{tool_name}' is unavailable (likely missing dependencies)"
                )

    tools = []
    for tool in get_available_tools():
        if allowlist is not None and not tool.is_mcp and tool.name not in allowlist:
            continue
        if not tool.is_available:
            continue
        if tool.disabled_by_default:
            if allowlist is None or tool.name not in allowlist:

Review comment (suggestion):
```suggestion
    # Validate allowlist if provided
    # TODO: maybe check in CLI init instead, as this might hard error in the server when loading conversations where tools are not available
```

Code after:
                allowlist = env_allowlist.split(",")
            elif config.chat and config.chat.tools:
                allowlist = config.chat.tools

        for tool in get_toolchain(allowlist):
            if tool in loaded_tools:
                # logger.warning("Tool '%s' already loaded", tool.name)
                continue
            if tool.init:
                tool = tool.init()

            loaded_tools.append(tool)

        for tool_name in allowlist or []:
            if not has_tool(tool_name):
                # if the tool is found but unavailable, we log a warning
                if tool_name in [tool.name for tool in get_available_tools()]:
                    logger.warning("Tool %s found but is unavailable", tool_name)
                    continue
                raise ValueError(f"Tool '{tool_name}' not found")

        return loaded_tools


def get_toolchain(allowlist: list[str] | None) -> list[ToolSpec]:
    # Validate allowlist if provided
    # TODO: maybe check in CLI init instead, as this might hard error in the server when loading conversations where tools are not available
    if allowlist is not None:
        available_tools = get_available_tools()
        available_tool_names = [tool.name for tool in available_tools]

        for tool_name in allowlist:
            if tool_name not in available_tool_names:
                raise ValueError(
                    f"Tool '{tool_name}' not found. Available tools: {', '.join(sorted(available_tool_names))}"
                )

            # Check if tool is available
            tool_obj = next(tool for tool in available_tools if tool.name == tool_name)
            if not tool_obj.is_available:
                raise ValueError(
                    f"Tool '{tool_name}' is unavailable (likely missing dependencies)"
                )

    tools = []
    for tool in get_available_tools():
        if allowlist is not None and not tool.is_mcp and tool.name not in allowlist:
            continue
        if not tool.is_available:
            continue
        if tool.disabled_by_default: