# This file was auto-generated by Fern from our API Definition.

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.cancel_stream_response import CancelStreamResponse
from ..types.input_message import InputMessage
from ..types.output_modes_response import OutputModesResponse
from ..types.partial_context import PartialContext
from ..types.reasoning_config import ReasoningConfig
from ..types.reasoning_levels_response import ReasoningLevelsResponse
from .types.chat_request_tools_item import ChatRequestToolsItem

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawResponsesClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def get_output_modes(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[OutputModesResponse]:
        """
        Get all available output modes.

        Returns list of supported output modes with descriptions and default flag.
        Requires authentication (Bearer token or API key).

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[OutputModesResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/model/response/output-modes",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    OutputModesResponse,
                    parse_obj_as(
                        type_=OutputModesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_reasoning_levels(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[ReasoningLevelsResponse]:
        """
        Get all available reasoning effort levels.

        Returns list of supported reasoning levels with descriptions and default flag.
        Requires authentication (Bearer token or API key).

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[ReasoningLevelsResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/model/response/reasoning-levels",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReasoningLevelsResponse,
                    parse_obj_as(
                        type_=ReasoningLevelsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def cancel_stream(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CancelStreamResponse]:
        """
        Cancel an active streaming response.

        Behavior depends on how long the stream has been running:
        - Within threshold (default 5s): "quick_edit" mode - both user message and
          assistant response are deleted, allowing the user to edit and resend.
        - After threshold: "keep_partial" mode - user message stays, partial
          assistant response is saved with cancelled status.

        The threshold is configurable via STREAM_CANCEL_QUICK_EDIT_THRESHOLD_SECONDS.

        Parameters
        ----------
        thread_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[CancelStreamResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/model/response/{jsonable_encoder(thread_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelStreamResponse,
                    parse_obj_as(
                        type_=CancelStreamResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_response(
        self,
        *,
        inputs: typing.Sequence[InputMessage],
        organization_id: typing.Optional[str] = OMIT,
        thread_id: typing.Optional[str] = OMIT,
        assistant_id: typing.Optional[str] = OMIT,
        assistant_name: typing.Optional[str] = OMIT,
        assistant_description: typing.Optional[str] = OMIT,
        assistant_instructions: typing.Optional[str] = OMIT,
        workflow_id: typing.Optional[str] = OMIT,
        vector_store_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        slice_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        space_id: typing.Optional[str] = OMIT,
        previous_response_id: typing.Optional[str] = OMIT,
        edit_message_id: typing.Optional[str] = OMIT,
        previous_message_id: typing.Optional[str] = OMIT,
        model: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.Sequence[ChatRequestToolsItem]] = OMIT,
        stream: typing.Optional[bool] = OMIT,
        instructions: typing.Optional[str] = OMIT,
        temperature: typing.Optional[float] = OMIT,
        top_p: typing.Optional[float] = OMIT,
        max_output_synapses: typing.Optional[int] = OMIT,
        max_completion_tokens: typing.Optional[int] = OMIT,
        frequency_penalty: typing.Optional[float] = OMIT,
        presence_penalty: typing.Optional[float] = OMIT,
        max_tool_calls: typing.Optional[int] = OMIT,
        parallel_tool_calls: typing.Optional[bool] = OMIT,
        service_tier: typing.Optional[str] = OMIT,
        thread_context_mode: typing.Optional[str] = OMIT,
        reasoning: typing.Optional[ReasoningConfig] = OMIT,
        include: typing.Optional[typing.Sequence[str]] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        disable_rules: typing.Optional[bool] = OMIT,
        store: typing.Optional[bool] = OMIT,
        partial_context: typing.Optional[PartialContext] = OMIT,
        output_mode: typing.Optional[str] = OMIT,
        system_tools: typing.Optional[typing.Dict[str, typing.Optional[typing.Dict[str, typing.Any]]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[typing.Any]:
        """
        Create AI response from inputs (Aitronos API compatible).

        For streaming: Uses lightweight auth (no DB queries) for <200ms TTFT.
        For non-streaming: Full auth validation happens synchronously.

        Parameters
        ----------
        inputs : typing.Sequence[InputMessage]
            Array of input messages. Last user message is the query.

        organization_id : typing.Optional[str]
            Organization ID. Required if user belongs to multiple organizations. Auto-selected if user belongs to exactly one organization. Returns error if user belongs to no organizations.

        thread_id : typing.Optional[str]
            Thread ID to continue conversation. Creates new thread if null.

        assistant_id : typing.Optional[str]
            Assistant ID to bind to thread. Can only be set when creating a new thread or on the first message. Once a thread has messages, the assistant binding is locked.

        assistant_name : typing.Optional[str]
            Assistant name for identity prompt (playground preview mode). Ignored if assistant_id is provided.

        assistant_description : typing.Optional[str]
            Assistant description for identity prompt (playground preview mode). Ignored if assistant_id is provided.

        assistant_instructions : typing.Optional[str]
            Assistant system instructions (playground preview mode). These are the assistant's core instructions, different from the 'instructions' field which provides additional per-request context. Ignored if assistant_id is provided.

        workflow_id : typing.Optional[str]
            Workflow/Flow ID from FlowPlate. Used to associate threads with specific workflows for filtering and organization. Can only be set when creating a new thread.

        vector_store_ids : typing.Optional[typing.Sequence[str]]
            Vector store IDs for file search/RAG. Enables searching uploaded files to answer questions. Alternative to using assistant with file_search tool.

        slice_ids : typing.Optional[typing.Sequence[str]]
            Knowledge slice IDs for file search/RAG (playground preview mode). Slices are resolved to vector store IDs and merged with vector_store_ids.

        space_id : typing.Optional[str]
            Space ID to associate the thread with. New threads are automatically added to this space. The space's dedicated and additional vector stores are merged into the conversation's knowledge sources.

        previous_response_id : typing.Optional[str]
            Response ID to reset context from. Messages after this point are ignored, enabling conversation reset after message edits.

        edit_message_id : typing.Optional[str]
            Message ID to edit. Soft-deletes this message and all subsequent messages, then uses the new input as the replacement. Requires thread_id. Cannot be used with previous_response_id or previous_message_id.

        previous_message_id : typing.Optional[str]
            Message ID to branch from. Soft-deletes all messages AFTER this message (keeping the target), then continues the thread with new input. Requires thread_id. Cannot be used with edit_message_id or previous_response_id.

        model : typing.Optional[str]
            Model key from the Freddy model catalog (e.g., 'gpt-4o', 'claude-3-5-sonnet')

        tools : typing.Optional[typing.Sequence[ChatRequestToolsItem]]
            Array of tool configurations (function tools or personal connectors)

        stream : typing.Optional[bool]
            Enable streaming (SSE). Default false returns complete response.

        instructions : typing.Optional[str]
            System instructions defining model behavior

        temperature : typing.Optional[float]
            Randomness (0.0-1.0). Lower=focused, higher=creative

        top_p : typing.Optional[float]
            Nucleus sampling (0.0-1.0). Alternative to temperature. Note: Some models only support one sampling parameter; if both are provided, an error will be returned.

        max_output_synapses : typing.Optional[int]
            Maximum output length (tokens)

        max_completion_tokens : typing.Optional[int]
            Alias for max_output_synapses. Maximum output length (tokens). If both max_output_synapses and max_completion_tokens are provided, max_completion_tokens takes precedence.

        frequency_penalty : typing.Optional[float]
            Penalizes tokens based on frequency in text so far (0.0-2.0). Higher values reduce repetition.

        presence_penalty : typing.Optional[float]
            Penalizes tokens based on whether they appear in text so far (0.0-2.0). Higher values increase topic diversity.

        max_tool_calls : typing.Optional[int]
            Maximum number of tool calls per response (1-50). Default 10.

        parallel_tool_calls : typing.Optional[bool]
            Whether to allow parallel tool execution. Default true.

        service_tier : typing.Optional[str]
            Processing tier for requests. Options: 'auto', 'default', 'flex', 'priority'.

        thread_context_mode : typing.Optional[str]
            Thread context mode controlling how much conversation history is included. Options: 'full', 'auto', 'off', 'saver'.

        reasoning : typing.Optional[ReasoningConfig]
            Unified reasoning configuration for reasoning-capable models. Controls computational effort and optional reasoning summary. API automatically maps to provider-specific parameters.

        include : typing.Optional[typing.Sequence[str]]
            Specify additional data to include in the response. Options: 'all', 'tools.available', 'tools.used', 'web_search.sources', 'code_interpreter.outputs', 'file_search.results', 'message.logprobs', 'reasoning.encrypted', 'request.logs', 'usage.detailed', 'rules.debug', 'rules'

        metadata : typing.Optional[typing.Dict[str, typing.Any]]
            Custom key-value pairs for tracking

        disable_rules : typing.Optional[bool]
            Disable user-level rule application (assistant, user, vector_store). System-level rules (model, organization) are always applied.

        store : typing.Optional[bool]
            Controls thread visibility. When true (default), thread appears in list. When false, thread is hidden from list (useful for internal operations, background tasks).

        partial_context : typing.Optional[PartialContext]
            Partial state from an interrupted stream. Send this when resuming after a stream drop so the LLM can continue where it left off.

        output_mode : typing.Optional[str]
            Response format mode. Options: 'text' (default, rich text with markdown), 'plain' (plain text with all formatting removed), 'structured' (typed blocks for custom UI rendering). Affects both streaming events and response_blocks field.

        system_tools : typing.Optional[typing.Dict[str, typing.Optional[typing.Dict[str, typing.Any]]]]
            System tools configuration. Overrides assistant configuration. Format: {'toolKey': {'mode': 'on|off|auto', ...}}. Available tools: web_search, code_interpreter, image_operations, file_search. Example: {'image_operations': {'mode': 'on'}}

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[typing.Any]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/model/response",
            method="POST",
            json={
                "inputs": convert_and_respect_annotation_metadata(
                    object_=inputs, annotation=typing.Sequence[InputMessage], direction="write"
                ),
                "organization_id": organization_id,
                "thread_id": thread_id,
                "assistant_id": assistant_id,
                "assistant_name": assistant_name,
                "assistant_description": assistant_description,
                "assistant_instructions": assistant_instructions,
                "workflow_id": workflow_id,
                "vector_store_ids": vector_store_ids,
                "slice_ids": slice_ids,
                "space_id": space_id,
                "previous_response_id": previous_response_id,
                "edit_message_id": edit_message_id,
                "previous_message_id": previous_message_id,
                "model": model,
                "tools": convert_and_respect_annotation_metadata(
                    object_=tools, annotation=typing.Optional[typing.Sequence[ChatRequestToolsItem]], direction="write"
                ),
                "stream": stream,
                "instructions": instructions,
                "temperature": temperature,
                "top_p": top_p,
                "max_output_synapses": max_output_synapses,
                "max_completion_tokens": max_completion_tokens,
                "frequency_penalty": frequency_penalty,
                "presence_penalty": presence_penalty,
                "max_tool_calls": max_tool_calls,
                "parallel_tool_calls": parallel_tool_calls,
                "service_tier": service_tier,
                "thread_context_mode": thread_context_mode,
                "reasoning": convert_and_respect_annotation_metadata(
                    object_=reasoning, annotation=typing.Optional[ReasoningConfig], direction="write"
                ),
                "include": include,
                "metadata": metadata,
                "disable_rules": disable_rules,
                "store": store,
                "partial_context": convert_and_respect_annotation_metadata(
                    object_=partial_context, annotation=typing.Optional[PartialContext], direction="write"
                ),
                "output_mode": output_mode,
                "system_tools": system_tools,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if _response is None or not _response.text.strip():
                return HttpResponse(response=_response, data=None)
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.Any,
                    parse_obj_as(
                        type_=typing.Any,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawResponsesClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def get_output_modes(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[OutputModesResponse]:
        """
        Get all available output modes.

        Returns list of supported output modes with descriptions and default flag.
        Requires authentication (Bearer token or API key).

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[OutputModesResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/model/response/output-modes",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    OutputModesResponse,
                    parse_obj_as(
                        type_=OutputModesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_reasoning_levels(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[ReasoningLevelsResponse]:
        """
        Get all available reasoning effort levels.

        Returns list of supported reasoning levels with descriptions and default flag.
        Requires authentication (Bearer token or API key).

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[ReasoningLevelsResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/model/response/reasoning-levels",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReasoningLevelsResponse,
                    parse_obj_as(
                        type_=ReasoningLevelsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def cancel_stream(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CancelStreamResponse]:
        """
        Cancel an active streaming response.

        Behavior depends on how long the stream has been running:
        - Within threshold (default 5s): "quick_edit" mode - both user message and
          assistant response are deleted, allowing the user to edit and resend.
        - After threshold: "keep_partial" mode - user message stays, partial
          assistant response is saved with cancelled status.

        The threshold is configurable via STREAM_CANCEL_QUICK_EDIT_THRESHOLD_SECONDS.

        Parameters
        ----------
        thread_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[CancelStreamResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/model/response/{jsonable_encoder(thread_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelStreamResponse,
                    parse_obj_as(
                        type_=CancelStreamResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_response(
        self,
        *,
        inputs: typing.Sequence[InputMessage],
        organization_id: typing.Optional[str] = OMIT,
        thread_id: typing.Optional[str] = OMIT,
        assistant_id: typing.Optional[str] = OMIT,
        assistant_name: typing.Optional[str] = OMIT,
        assistant_description: typing.Optional[str] = OMIT,
        assistant_instructions: typing.Optional[str] = OMIT,
        workflow_id: typing.Optional[str] = OMIT,
        vector_store_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        slice_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        space_id: typing.Optional[str] = OMIT,
        previous_response_id: typing.Optional[str] = OMIT,
        edit_message_id: typing.Optional[str] = OMIT,
        previous_message_id: typing.Optional[str] = OMIT,
        model: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.Sequence[ChatRequestToolsItem]] = OMIT,
        stream: typing.Optional[bool] = OMIT,
        instructions: typing.Optional[str] = OMIT,
        temperature: typing.Optional[float] = OMIT,
        top_p: typing.Optional[float] = OMIT,
        max_output_synapses: typing.Optional[int] = OMIT,
        max_completion_tokens: typing.Optional[int] = OMIT,
        frequency_penalty: typing.Optional[float] = OMIT,
        presence_penalty: typing.Optional[float] = OMIT,
        max_tool_calls: typing.Optional[int] = OMIT,
        parallel_tool_calls: typing.Optional[bool] = OMIT,
        service_tier: typing.Optional[str] = OMIT,
        thread_context_mode: typing.Optional[str] = OMIT,
        reasoning: typing.Optional[ReasoningConfig] = OMIT,
        include: typing.Optional[typing.Sequence[str]] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        disable_rules: typing.Optional[bool] = OMIT,
        store: typing.Optional[bool] = OMIT,
        partial_context: typing.Optional[PartialContext] = OMIT,
        output_mode: typing.Optional[str] = OMIT,
        system_tools: typing.Optional[typing.Dict[str, typing.Optional[typing.Dict[str, typing.Any]]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[typing.Any]:
        """
        Create AI response from inputs (Aitronos API compatible).

        For streaming: Uses lightweight auth (no DB queries) for <200ms TTFT.
        For non-streaming: Full auth validation happens synchronously.

        Parameters
        ----------
        inputs : typing.Sequence[InputMessage]
            Array of input messages. Last user message is the query.

        organization_id : typing.Optional[str]
            Organization ID. Required if user belongs to multiple organizations. Auto-selected if user belongs to exactly one organization. Returns error if user belongs to no organizations.

        thread_id : typing.Optional[str]
            Thread ID to continue conversation. Creates new thread if null.

        assistant_id : typing.Optional[str]
            Assistant ID to bind to thread. Can only be set when creating a new thread or on the first message. Once a thread has messages, the assistant binding is locked.

        assistant_name : typing.Optional[str]
            Assistant name for identity prompt (playground preview mode). Ignored if assistant_id is provided.

        assistant_description : typing.Optional[str]
            Assistant description for identity prompt (playground preview mode). Ignored if assistant_id is provided.

        assistant_instructions : typing.Optional[str]
            Assistant system instructions (playground preview mode). These are the assistant's core instructions, different from the 'instructions' field which provides additional per-request context. Ignored if assistant_id is provided.

        workflow_id : typing.Optional[str]
            Workflow/Flow ID from FlowPlate. Used to associate threads with specific workflows for filtering and organization. Can only be set when creating a new thread.

        vector_store_ids : typing.Optional[typing.Sequence[str]]
            Vector store IDs for file search/RAG. Enables searching uploaded files to answer questions. Alternative to using assistant with file_search tool.

        slice_ids : typing.Optional[typing.Sequence[str]]
            Knowledge slice IDs for file search/RAG (playground preview mode). Slices are resolved to vector store IDs and merged with vector_store_ids.

        space_id : typing.Optional[str]
            Space ID to associate the thread with. New threads are automatically added to this space. The space's dedicated and additional vector stores are merged into the conversation's knowledge sources.

        previous_response_id : typing.Optional[str]
            Response ID to reset context from. Messages after this point are ignored, enabling conversation reset after message edits.

        edit_message_id : typing.Optional[str]
            Message ID to edit. Soft-deletes this message and all subsequent messages, then uses the new input as the replacement. Requires thread_id. Cannot be used with previous_response_id or previous_message_id.

        previous_message_id : typing.Optional[str]
            Message ID to branch from. Soft-deletes all messages AFTER this message (keeping the target), then continues the thread with new input. Requires thread_id. Cannot be used with edit_message_id or previous_response_id.

        model : typing.Optional[str]
            Model key from the Freddy model catalog (e.g., 'gpt-4o', 'claude-3-5-sonnet')

        tools : typing.Optional[typing.Sequence[ChatRequestToolsItem]]
            Array of tool configurations (function tools or personal connectors)

        stream : typing.Optional[bool]
            Enable streaming (SSE). Default false returns complete response.

        instructions : typing.Optional[str]
            System instructions defining model behavior

        temperature : typing.Optional[float]
            Randomness (0.0-1.0). Lower=focused, higher=creative

        top_p : typing.Optional[float]
            Nucleus sampling (0.0-1.0). Alternative to temperature. Note: Some models only support one sampling parameter; if both are provided, an error will be returned.

        max_output_synapses : typing.Optional[int]
            Maximum output length (tokens)

        max_completion_tokens : typing.Optional[int]
            Alias for max_output_synapses. Maximum output length (tokens). If both max_output_synapses and max_completion_tokens are provided, max_completion_tokens takes precedence.

        frequency_penalty : typing.Optional[float]
            Penalizes tokens based on frequency in text so far (0.0-2.0). Higher values reduce repetition.

        presence_penalty : typing.Optional[float]
            Penalizes tokens based on whether they appear in text so far (0.0-2.0). Higher values increase topic diversity.

        max_tool_calls : typing.Optional[int]
            Maximum number of tool calls per response (1-50). Default 10.

        parallel_tool_calls : typing.Optional[bool]
            Whether to allow parallel tool execution. Default true.

        service_tier : typing.Optional[str]
            Processing tier for requests. Options: 'auto', 'default', 'flex', 'priority'.

        thread_context_mode : typing.Optional[str]
            Thread context mode controlling how much conversation history is included. Options: 'full', 'auto', 'off', 'saver'.

        reasoning : typing.Optional[ReasoningConfig]
            Unified reasoning configuration for reasoning-capable models. Controls computational effort and optional reasoning summary. API automatically maps to provider-specific parameters.

        include : typing.Optional[typing.Sequence[str]]
            Specify additional data to include in the response. Options: 'all', 'tools.available', 'tools.used', 'web_search.sources', 'code_interpreter.outputs', 'file_search.results', 'message.logprobs', 'reasoning.encrypted', 'request.logs', 'usage.detailed', 'rules.debug', 'rules'

        metadata : typing.Optional[typing.Dict[str, typing.Any]]
            Custom key-value pairs for tracking

        disable_rules : typing.Optional[bool]
            Disable user-level rule application (assistant, user, vector_store). System-level rules (model, organization) are always applied.

        store : typing.Optional[bool]
            Controls thread visibility. When true (default), thread appears in list. When false, thread is hidden from list (useful for internal operations, background tasks).

        partial_context : typing.Optional[PartialContext]
            Partial state from an interrupted stream. Send this when resuming after a stream drop so the LLM can continue where it left off.

        output_mode : typing.Optional[str]
            Response format mode. Options: 'text' (default, rich text with markdown), 'plain' (plain text with all formatting removed), 'structured' (typed blocks for custom UI rendering). Affects both streaming events and response_blocks field.

        system_tools : typing.Optional[typing.Dict[str, typing.Optional[typing.Dict[str, typing.Any]]]]
            System tools configuration. Overrides assistant configuration. Format: {'toolKey': {'mode': 'on|off|auto', ...}}. Available tools: web_search, code_interpreter, image_operations, file_search. Example: {'image_operations': {'mode': 'on'}}

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[typing.Any]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/model/response",
            method="POST",
            json={
                "inputs": convert_and_respect_annotation_metadata(
                    object_=inputs, annotation=typing.Sequence[InputMessage], direction="write"
                ),
                "organization_id": organization_id,
                "thread_id": thread_id,
                "assistant_id": assistant_id,
                "assistant_name": assistant_name,
                "assistant_description": assistant_description,
                "assistant_instructions": assistant_instructions,
                "workflow_id": workflow_id,
                "vector_store_ids": vector_store_ids,
                "slice_ids": slice_ids,
                "space_id": space_id,
                "previous_response_id": previous_response_id,
                "edit_message_id": edit_message_id,
                "previous_message_id": previous_message_id,
                "model": model,
                "tools": convert_and_respect_annotation_metadata(
                    object_=tools, annotation=typing.Optional[typing.Sequence[ChatRequestToolsItem]], direction="write"
                ),
                "stream": stream,
                "instructions": instructions,
                "temperature": temperature,
                "top_p": top_p,
                "max_output_synapses": max_output_synapses,
                "max_completion_tokens": max_completion_tokens,
                "frequency_penalty": frequency_penalty,
                "presence_penalty": presence_penalty,
                "max_tool_calls": max_tool_calls,
                "parallel_tool_calls": parallel_tool_calls,
                "service_tier": service_tier,
                "thread_context_mode": thread_context_mode,
                "reasoning": convert_and_respect_annotation_metadata(
                    object_=reasoning, annotation=typing.Optional[ReasoningConfig], direction="write"
                ),
                "include": include,
                "metadata": metadata,
                "disable_rules": disable_rules,
                "store": store,
                "partial_context": convert_and_respect_annotation_metadata(
                    object_=partial_context, annotation=typing.Optional[PartialContext], direction="write"
                ),
                "output_mode": output_mode,
                "system_tools": system_tools,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if _response is None or not _response.text.strip():
                return AsyncHttpResponse(response=_response, data=None)
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.Any,
                    parse_obj_as(
                        type_=typing.Any,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
