Skip to content

[BUG]: FREISA-GPT raises TypeError after every successful tool call #111

Open

Description

@gmacario

Description of the bug

ChatSession.process_user_request() raises TypeError whenever a tool call succeeds — i.e. on the main FREISA-GPT path.

LLMClient.get_response() is annotated -> str and returns a JSON string (llm_client.py:86):

return json.dumps(data["choices"][0]["message"])

But the caller indexes it as if it were a dict, at mcp_client.py:404:

final_response = await self.llm_client.get_response(messages)
...
return final_response["content"]   # <-- TypeError: string indices must be integers

Steps To Reproduce

This branch is taken whenever process_llm_response() actually executes a tool (so result != llm_response). Minimal reproduction of the type confusion:

import json

def get_response() -> str:                      # mirrors LLMClient.get_response
    return json.dumps({"role": "assistant", "content": "Woof!"})

final_response = get_response()
print(final_response["content"])                # mcp_client.py:404
# TypeError: string indices must be integers, not 'str'

Confirmed statically by mypy:

src/mcp_client_pupper/mcp_client.py:404: error: Invalid index type "str" for "str";
    expected type "SupportsIndex | slice[...]"  [index]

Additional Information

The exception is not caught anywhere on the way up: process_user_request() is awaited unguarded in PuppyVoiceAssistant._process_heard_text(), which is itself driven from asyncio.run(...) inside the sounddevice audio callback (puppy_voice_assistant.py:145). So the failure surfaces inside the realtime audio thread rather than as a clean error.

Possible fixes:

  • Have get_response() return the parsed dict (and update the annotation and the other three call sites), or
  • json.loads(final_response)["content"] at the call site.

The first is cleaner: llm_response is already json.loads-ed again inside process_llm_response(), so the round-trip through a string serves no purpose.

mypy also flags three Item "None" of "LLMClient | None" has no attribute "get_response" errors in the same file — ChatSession.llm_client is typed Optional[LLMClient] but never narrowed.

Note

Found during an automated code audit; see also the related issues filed at the same time.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions