Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
eba2bae
feat(mistral): Add integration with Chat.complete and Chat.complete_a…
alexander-alderman-webb Sep 17, 2026
4b57f72
.
alexander-alderman-webb Sep 17, 2026
08b3eb0
.
alexander-alderman-webb Sep 17, 2026
e5c7c9a
.
alexander-alderman-webb Sep 17, 2026
e07fee8
feat(mistral): Record token usage
alexander-alderman-webb Sep 17, 2026
544f550
feat(mistral): Record request parameters
alexander-alderman-webb Sep 17, 2026
03d5fe0
feat(mistral): Record gen_ai.system_instructions
alexander-alderman-webb Sep 21, 2026
8e1f0ce
feat(mistral): Record gen_ai.input.messages
alexander-alderman-webb Sep 21, 2026
cb02dfa
merge master and address comments
alexander-alderman-webb Sep 21, 2026
6cc054a
merge
alexander-alderman-webb Sep 21, 2026
e9d366a
Merge branch 'webb/mistral/tokens' into webb/mistral/configuration-at…
alexander-alderman-webb Sep 21, 2026
4006ba1
Merge branch 'webb/mistral/configuration-attributes' into webb/mistra…
alexander-alderman-webb Sep 21, 2026
510e93b
Merge branch 'webb/mistral/input-messages' into webb/mistral/input-me…
alexander-alderman-webb Sep 21, 2026
ca088a2
sensitive data gating
alexander-alderman-webb Sep 21, 2026
7f44ed2
sensitive data gating
alexander-alderman-webb Sep 21, 2026
4e2b954
.
alexander-alderman-webb Sep 21, 2026
4b631ad
.
alexander-alderman-webb Sep 21, 2026
0bca24b
Merge branch 'webb/mistral/chat-complete' into webb/mistral/tokens
alexander-alderman-webb Sep 21, 2026
38552dc
merge
alexander-alderman-webb Sep 21, 2026
ebe8ba7
Merge branch 'webb/mistral/configuration-attributes' into webb/mistra…
alexander-alderman-webb Sep 21, 2026
6e85c46
Merge branch 'webb/mistral/input-messages' into webb/mistral/input-me…
alexander-alderman-webb Sep 21, 2026
9391c09
fix assistant message recording
alexander-alderman-webb Sep 21, 2026
9cc9bef
take out of auto-enabling
alexander-alderman-webb Sep 21, 2026
203b691
Merge branch 'webb/mistral/chat-complete' into webb/mistral/tokens
alexander-alderman-webb Sep 21, 2026
14a680f
Merge branch 'webb/mistral/tokens' into webb/mistral/configuration-at…
alexander-alderman-webb Sep 21, 2026
15e7eee
Merge branch 'webb/mistral/configuration-attributes' into webb/mistra…
alexander-alderman-webb Sep 21, 2026
7f5e00c
use role var
alexander-alderman-webb Sep 21, 2026
bd4fbeb
add assistant message to tests
alexander-alderman-webb Sep 21, 2026
e21572c
handle None Model
alexander-alderman-webb Sep 21, 2026
ae22b23
generate GH workflows
alexander-alderman-webb Sep 21, 2026
eb04a75
Merge branch 'webb/mistral/chat-complete' into webb/mistral/tokens
alexander-alderman-webb Sep 21, 2026
6bb297f
Merge branch 'webb/mistral/tokens' into webb/mistral/configuration-at…
alexander-alderman-webb Sep 21, 2026
101712a
Merge branch 'webb/mistral/configuration-attributes' into webb/mistra…
alexander-alderman-webb Sep 21, 2026
930be7b
Merge branch 'webb/mistral/input-messages' into webb/mistral/input-me…
alexander-alderman-webb Sep 21, 2026
868ea47
raise min version to 2.0.5
alexander-alderman-webb Sep 21, 2026
e19d1f0
Merge branch 'webb/mistral/chat-complete' into webb/mistral/tokens
alexander-alderman-webb Sep 21, 2026
b20f5f0
Merge branch 'webb/mistral/tokens' into webb/mistral/configuration-at…
alexander-alderman-webb Sep 21, 2026
fc26917
Merge branch 'webb/mistral/configuration-attributes' into webb/mistra…
alexander-alderman-webb Sep 21, 2026
38f7e39
Merge branch 'webb/mistral/input-messages' into webb/mistral/input-me…
alexander-alderman-webb Sep 21, 2026
4e885fb
test: use high reasoning level
alexander-alderman-webb Sep 21, 2026
f46f2bf
update assertions
alexander-alderman-webb Sep 21, 2026
3484c62
Merge branch 'webb/mistral/configuration-attributes' into webb/mistra…
alexander-alderman-webb Sep 21, 2026
6ffb3d0
Merge branch 'webb/mistral/input-messages' into webb/mistral/input-me…
alexander-alderman-webb Sep 21, 2026
19e8626
merge master
alexander-alderman-webb Sep 21, 2026
32f61e4
check type property
alexander-alderman-webb Sep 21, 2026
dac3f9d
Merge branch 'webb/mistral/input-messages' into webb/mistral/input-me…
alexander-alderman-webb Sep 21, 2026
11fb6e1
merge master
alexander-alderman-webb Sep 21, 2026
56f33cc
check type
alexander-alderman-webb Sep 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions sentry_sdk/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,10 @@ class ToolCallPart(TypedDict):
name: NotRequired[str]
arguments: NotRequired[Any]

class InputMessage(TypedDict):
role: Literal["user", "assistant", "tool"]
parts: list[Union[TextPart, ReasoningPart, ToolCallPart]]

class ToolDefinition(TypedDict):
type: str
name: NotRequired[str]
Expand Down
99 changes: 98 additions & 1 deletion sentry_sdk/integrations/mistral.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@
TextChunkTypedDict,
)

from sentry_sdk._types import TextPart
from sentry_sdk._types import InputMessage, TextPart

try:
from mistralai.client.chat import Chat
from mistralai.client.models import (
AssistantMessage,
ChatCompletionResponse,
SystemMessage,
TextChunk,
UserMessage,
)
except ImportError:
raise DidNotEnable("mistralai not installed")
Expand Down Expand Up @@ -61,6 +63,91 @@ def _is_system_instruction(
return False


def _transform_input_messages(
messages: "Sequence[Union[ChatCompletionRequestMessage, ChatCompletionRequestMessageTypedDict]]",
) -> "list[InputMessage]":
input_messages: "list[InputMessage]" = []

for message in messages:
if isinstance(message, UserMessage) and isinstance(message.content, str):
input_messages.append(
{
"role": "user",
"parts": [{"type": "text", "content": message.content}],
}
)
elif isinstance(message, UserMessage) and isinstance(message.content, list):
text_parts = [
part for part in message.content if isinstance(part, TextChunk)
]
input_messages.append(
{
"role": "user",
"parts": [
{"type": "text", "content": part.text} for part in text_parts
],
}
)
Comment thread
alexander-alderman-webb marked this conversation as resolved.

if isinstance(message, AssistantMessage) and isinstance(message.content, str):
input_messages.append(
{
"role": "assistant",
"parts": [{"type": "text", "content": message.content}],
Comment thread
alexander-alderman-webb marked this conversation as resolved.
}
)
elif isinstance(message, AssistantMessage) and isinstance(
message.content, list
):
text_parts = [
part for part in message.content if isinstance(part, TextChunk)
]
input_messages.append(
{
"role": "assistant",
"parts": [
{"type": "text", "content": part.text} for part in text_parts
],
}
)

if not isinstance(message, dict):
continue

role = message.get("role")
if role != "user" and role != "assistant":
continue

content = message.get("content")
if isinstance(content, str):
input_messages.append(
{"role": role, "parts": [{"type": "text", "content": content}]}
)

if not isinstance(content, list):
continue
Comment thread
alexander-alderman-webb marked this conversation as resolved.

text_parts = [
part
for part in content
if isinstance(part, dict) and part.get("type") == "text" and "text" in part
]
input_messages.append(
{
"role": role,
"parts": [
{
"type": "text",
"content": cast("TextChunkTypedDict", part)["text"],
}
for part in text_parts
],
}
)

return input_messages


def _transform_system_instructions(
messages: "list[Union[SystemMessage, SystemMessageTypedDict]]",
) -> "list[TextPart]":
Expand Down Expand Up @@ -157,6 +244,11 @@ def wrap_complete(self: "Chat", *args: "Any", **kwargs: "Any") -> "Any":
json.dumps(_transform_system_instructions(system_instructions)),
)

set_on_span(
SPANDATA.GEN_AI_INPUT_MESSAGES,
json.dumps(_transform_input_messages(messages)),
)

max_tokens = kwargs.get("max_tokens")
if max_tokens is not None:
set_on_span(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens)
Expand Down Expand Up @@ -270,6 +362,11 @@ async def wrap_complete_async(self: "Chat", *args: "Any", **kwargs: "Any") -> "A
json.dumps(_transform_system_instructions(system_instructions)),
)

set_on_span(
SPANDATA.GEN_AI_INPUT_MESSAGES,
json.dumps(_transform_input_messages(messages)),
)

max_tokens = kwargs.get("max_tokens")
if max_tokens is not None:
set_on_span(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens)
Expand Down
Loading
Loading