Skip to content

Commit e234284

Browse files
Copilotstephentoub
andcommitted
Address PR feedback: improve DebuggerDisplay implementations
- Use proper base64 decoding with Base64.IsValid on NET or Convert.FromBase64String - Add helper method GetBase64LengthDisplay for consistent base64 length display - Use string literals in DebuggerDisplay attributes where possible - Put URIs in quotes for better readability - Use Text ?? "" and Uri ?? "" for null safety in ToString and DebuggerDisplay Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
1 parent f74c0c9 commit e234284

File tree

4 files changed

+56
-34
lines changed

4 files changed

+56
-34
lines changed

src/ModelContextProtocol.Core/Protocol/BlobResourceContents.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,30 @@ private string DebuggerDisplay
3535
{
3636
get
3737
{
38-
// Decode base64 to get actual byte length
39-
int byteLength = Blob.Length * 3 / 4;
38+
string lengthDisplay;
39+
try
40+
{
41+
#if NET
42+
if (System.Buffers.Text.Base64.IsValid(System.Text.Encoding.UTF8.GetBytes(Blob), out int decodedLength))
43+
{
44+
lengthDisplay = $"{decodedLength} bytes";
45+
}
46+
else
47+
{
48+
lengthDisplay = "invalid base64";
49+
}
50+
#else
51+
byte[] decoded = Convert.FromBase64String(Blob);
52+
lengthDisplay = $"{decoded.Length} bytes";
53+
#endif
54+
}
55+
catch
56+
{
57+
lengthDisplay = "invalid base64";
58+
}
59+
4060
string mimeInfo = MimeType is not null ? $", MimeType = {MimeType}" : "";
41-
return $"Uri = {Uri}{mimeInfo}, Length = {byteLength} bytes";
61+
return $"Uri = \"{Uri}\"{mimeInfo}, Length = {lengthDisplay}";
4262
}
4363
}
4464
}

src/ModelContextProtocol.Core/Protocol/ContentBlock.cs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,30 @@ private protected ContentBlock()
3232
{
3333
}
3434

35+
/// <summary>
36+
/// Helper method to get the decoded length of base64 data for debugger display.
37+
/// </summary>
38+
private protected static string GetBase64LengthDisplay(string base64Data)
39+
{
40+
try
41+
{
42+
#if NET
43+
if (System.Buffers.Text.Base64.IsValid(System.Text.Encoding.UTF8.GetBytes(base64Data), out int decodedLength))
44+
{
45+
return $"{decodedLength} bytes";
46+
}
47+
return "invalid base64";
48+
#else
49+
byte[] decoded = Convert.FromBase64String(base64Data);
50+
return $"{decoded.Length} bytes";
51+
#endif
52+
}
53+
catch
54+
{
55+
return "invalid base64";
56+
}
57+
}
58+
3559
/// <summary>
3660
/// When overridden in a derived class, gets the type of content.
3761
/// </summary>
@@ -356,7 +380,7 @@ public override void Write(Utf8JsonWriter writer, ContentBlock value, JsonSerial
356380
}
357381

358382
/// <summary>Represents text provided to or from an LLM.</summary>
359-
[DebuggerDisplay("{DebuggerDisplay,nq}")]
383+
[DebuggerDisplay("Text = \\\"{Text}\\\"")]
360384
public sealed class TextContentBlock : ContentBlock
361385
{
362386
/// <inheritdoc/>
@@ -369,10 +393,7 @@ public sealed class TextContentBlock : ContentBlock
369393
public required string Text { get; set; }
370394

371395
/// <inheritdoc/>
372-
public override string ToString() => Text;
373-
374-
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
375-
private string DebuggerDisplay => $"Text = \"{Text}\"";
396+
public override string ToString() => Text ?? "";
376397
}
377398

378399
/// <summary>Represents an image provided to or from an LLM.</summary>
@@ -398,15 +419,7 @@ public sealed class ImageContentBlock : ContentBlock
398419
public required string MimeType { get; set; }
399420

400421
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
401-
private string DebuggerDisplay
402-
{
403-
get
404-
{
405-
// Decode base64 to get actual byte length
406-
int byteLength = Data.Length * 3 / 4;
407-
return $"MimeType = {MimeType}, Length = {byteLength} bytes";
408-
}
409-
}
422+
private string DebuggerDisplay => $"MimeType = {MimeType}, Length = {GetBase64LengthDisplay(Data)}";
410423
}
411424

412425
/// <summary>Represents audio provided to or from an LLM.</summary>
@@ -432,15 +445,7 @@ public sealed class AudioContentBlock : ContentBlock
432445
public required string MimeType { get; set; }
433446

434447
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
435-
private string DebuggerDisplay
436-
{
437-
get
438-
{
439-
// Decode base64 to get actual byte length
440-
int byteLength = Data.Length * 3 / 4;
441-
return $"MimeType = {MimeType}, Length = {byteLength} bytes";
442-
}
443-
}
448+
private string DebuggerDisplay => $"MimeType = {MimeType}, Length = {GetBase64LengthDisplay(Data)}";
444449
}
445450

446451
/// <summary>Represents the contents of a resource, embedded into a prompt or tool call result.</summary>
@@ -467,14 +472,14 @@ public sealed class EmbeddedResourceBlock : ContentBlock
467472
public required ResourceContents Resource { get; set; }
468473

469474
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
470-
private string DebuggerDisplay => $"Uri = {Resource.Uri}";
475+
private string DebuggerDisplay => $"Uri = \"{Resource.Uri}\"";
471476
}
472477

473478
/// <summary>Represents a resource that the server is capable of reading, included in a prompt or tool call result.</summary>
474479
/// <remarks>
475480
/// Resource links returned by tools are not guaranteed to appear in the results of `resources/list` requests.
476481
/// </remarks>
477-
[DebuggerDisplay("{DebuggerDisplay,nq}")]
482+
[DebuggerDisplay("Name = {Name}, Uri = \\\"{Uri}\\\"")]
478483
public sealed class ResourceLinkBlock : ContentBlock
479484
{
480485
/// <inheritdoc/>
@@ -536,9 +541,6 @@ public sealed class ResourceLinkBlock : ContentBlock
536541
/// </remarks>
537542
[JsonPropertyName("size")]
538543
public long? Size { get; set; }
539-
540-
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
541-
private string DebuggerDisplay => $"Name = {Name}, Uri = {Uri}";
542544
}
543545

544546
/// <summary>Represents a request from the assistant to call a tool.</summary>

src/ModelContextProtocol.Core/Protocol/Icon.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private string DebuggerDisplay
9191
get
9292
{
9393
string mimeInfo = MimeType is not null ? $", MimeType = {MimeType}" : "";
94-
return $"Source = {Source}{mimeInfo}";
94+
return $"Source = \"{Source}\"{mimeInfo}";
9595
}
9696
}
9797
}

src/ModelContextProtocol.Core/Protocol/TextResourceContents.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace ModelContextProtocol.Protocol;
2020
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for more details.
2121
/// </para>
2222
/// </remarks>
23-
[DebuggerDisplay("Uri = {Uri}, Text = \\\"{Text}\\\"")]
23+
[DebuggerDisplay("Uri = \\\"{Uri}\\\", Text = \\\"{Text}\\\"")]
2424
public sealed class TextResourceContents : ResourceContents
2525
{
2626
/// <summary>
@@ -30,5 +30,5 @@ public sealed class TextResourceContents : ResourceContents
3030
public required string Text { get; set; }
3131

3232
/// <inheritdoc/>
33-
public override string ToString() => Text;
33+
public override string ToString() => Text ?? "";
3434
}

0 commit comments

Comments
 (0)