MCPcopy Index your code
hub / github.com/coder/coder / toolResultPartToMessagePart

Function toolResultPartToMessagePart

coderd/x/chatd/chatprompt/chatprompt.go:1370–1466  ·  view source on GitHub ↗

toolResultPartToMessagePart converts an SDK tool-result part into a fantasy ToolResultPart for LLM dispatch.

(logger slog.Logger, part codersdk.ChatMessagePart)

Source from the content-addressed store, hash-verified

1368// toolResultPartToMessagePart converts an SDK tool-result part
1369// into a fantasy ToolResultPart for LLM dispatch.
1370func toolResultPartToMessagePart(logger slog.Logger, part codersdk.ChatMessagePart) fantasy.ToolResultPart {
1371 toolCallID := sanitizeToolCallID(part.ToolCallID)
1372 resultText := string(part.Result)
1373 if resultText == "" || resultText == "null" {
1374 resultText = "{}"
1375 }
1376
1377 opts := providerMetadataToOptions(logger, part.ProviderMetadata)
1378
1379 if part.IsError {
1380 message := strings.TrimSpace(resultText)
1381 if extracted := extractErrorString(part.Result); extracted != "" {
1382 message = extracted
1383 }
1384 // Sanitize before wrapping in an error so that invalid
1385 // byte sequences from tool output do not propagate into
1386 // the LLM message stream.
1387 message = strings.ToValidUTF8(message, "\uFFFD")
1388 return fantasy.ToolResultPart{
1389 ToolCallID: toolCallID,
1390 ProviderExecuted: part.ProviderExecuted,
1391 Output: fantasy.ToolResultOutputContentError{
1392 Error: xerrors.New(message),
1393 },
1394 ProviderOptions: opts,
1395 }
1396 }
1397
1398 // IsError takes precedence and is handled above.
1399 // Detect media content flagged by toolResultContentToPart.
1400 // Screenshots from the computer use tool are stored as
1401 // {"data":"<base64>","mime_type":"image/png","text":"..."}
1402 // with optional attachment identity fields when the same image
1403 // was also promoted into a durable file part. Without this
1404 // detection, the entire base64 payload is sent as text tokens,
1405 // which quickly exceeds the context limit on follow-up messages.
1406 if part.IsMedia {
1407 var media persistedMediaResult
1408 unmarshalErr := json.Unmarshal(part.Result, &media)
1409 if unmarshalErr == nil && media.Data != "" && media.MimeType != "" {
1410 _, decErr := base64.StdEncoding.DecodeString(media.Data)
1411 if decErr == nil {
1412 return fantasy.ToolResultPart{
1413 ToolCallID: toolCallID,
1414 ProviderExecuted: part.ProviderExecuted,
1415 Output: fantasy.ToolResultOutputContentMedia{
1416 Data: media.Data,
1417 MediaType: media.MimeType,
1418 Text: strings.ToValidUTF8(media.Text, "\uFFFD"),
1419 },
1420 ProviderOptions: opts,
1421 }
1422 }
1423 // Base64 invalid. Use the human-readable annotation
1424 // instead of the full JSON blob to preserve context.
1425 logger.Warn(context.Background(),
1426 "tool result not valid base64, falling through to text",
1427 slog.F("tool_call_id", toolCallID),

Callers 1

partsToMessagePartsFunction · 0.85

Calls 7

sanitizeToolCallIDFunction · 0.85
extractErrorStringFunction · 0.85
DecodeStringMethod · 0.80
NewMethod · 0.65
UnmarshalMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected