result

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package result provides utilities for extracting and parsing JSON responses from AI models.

This package simplifies the process of handling AI model responses that often contain JSON data wrapped in markdown code blocks or other formatting. It provides type-safe extraction and unmarshaling of JSON content from text responses.

Overview

The result package offers the following key features:

  • Automatic extraction of JSON from markdown code blocks
  • Support for multiple markdown formats (```json, ```, inline)
  • Type-safe generic unmarshaling
  • Graceful handling of malformed responses
  • Thread-safe operations

Basic Usage

When working with AI model responses, you often receive JSON wrapped in markdown:

response := `Here is the data you requested:

```json
{
	"name": "example",
	"value": 42,
	"active": true
}
```
`

// Extract just the JSON content
jsonStr := result.ExtractJSON(response)
fmt.Println(jsonStr) // {"name": "example", "value": 42, "active": true}

// Or extract and unmarshal in one step
type Data struct {
	Name   string `json:"name"`
	Value  int    `json:"value"`
	Active bool   `json:"active"`
}

data, err := result.Extract[Data](response)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("%+v\n", data) // {Name:example Value:42 Active:true}

JSON Extraction

The ExtractJSON function handles various response formats:

1. Standard markdown code blocks:

```json
{"key": "value"}
```

2. Generic code blocks:

```
{"key": "value"}
```

3. Inline JSON (no markdown):

{"key": "value"}

4. JSON with surrounding text:

Here's your response:
```json
{"status": "success"}
```
Additional notes here.

Type-Safe Extraction

The generic Extract function combines JSON extraction with unmarshaling:

// Define your response structure
type FixResponse struct {
	Files []struct {
		Filename string `json:"filename"`
		Content  string `json:"content"`
	} `json:"files"`
	Description string `json:"description"`
}

// Extract from AI response
response := `I'll fix those files for you:

```json
{
	"files": [
		{
			"filename": "main.go",
			"content": "package main\n\nfunc main() {\n\t// Fixed\n}"
		}
	],
	"description": "Fixed the syntax error"
}
```
`

fix, err := result.Extract[FixResponse](response)
if err != nil {
	return err
}

for _, file := range fix.Files {
	fmt.Printf("Update %s\n", file.Filename)
}

Error Handling

The package handles various error conditions gracefully:

// Empty JSON block
response := "```json\n```"
data := result.ExtractJSON(response) // Returns ""

// Malformed JSON
response = "```json\n{invalid json}\n```"
var obj map[string]interface{}
_, err := result.Extract[map[string]interface{}](response)
// err will be a json.UnmarshalError

// No JSON found - returns trimmed input
response = "Just plain text"
data = result.ExtractJSON(response) // Returns "Just plain text"

Thread Safety

All functions in this package are thread-safe. They operate on immutable input strings and don't maintain any shared state, making them safe for concurrent use.

Integration with AI Services

This package is designed to work with responses from various AI services:

Claude example:

response, _ := claude.Complete(prompt)
analysis, err := result.Extract[AnalysisResult](response.Content)

Google Gemini example:

response, _ := gemini.Generate(prompt)
summary, err := result.Extract[Summary](response.Text)

OpenAI example:

response, _ := openai.CreateCompletion(prompt)
data, err := result.Extract[ResponseData](response.Choices[0].Text)

Performance Considerations

The package is optimized for typical AI response sizes:

  • Efficient string processing without regex
  • Single pass extraction for markdown blocks
  • Minimal memory allocations
  • No external dependencies beyond standard library

Common Patterns

Working with structured AI responses:

// Command AI to return specific JSON structure
prompt := `Analyze this code and return JSON in this format:
{
	"issues": [{"line": number, "message": "string", "severity": "string"}],
	"summary": "string"
}`

response := callAI(prompt)

type CodeAnalysis struct {
	Issues []struct {
		Line     int    `json:"line"`
		Message  string `json:"message"`
		Severity string `json:"severity"`
	} `json:"issues"`
	Summary string `json:"summary"`
}

analysis, err := result.Extract[CodeAnalysis](response)
if err != nil {
	// Handle extraction or parsing error
	return fmt.Errorf("failed to parse AI response: %w", err)
}

// Use the structured data
for _, issue := range analysis.Issues {
	fmt.Printf("Line %d: %s (%s)\n", issue.Line, issue.Message, issue.Severity)
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Extract

func Extract[T any](responseText string) (T, error)

Extract extracts JSON content from a text response and unmarshals it into the provided type. It combines ExtractJSON with json.Unmarshal for convenience.

Example

ExampleExtract demonstrates type-safe extraction and unmarshaling.

package main

import (
	"fmt"
	"log"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// AI response with structured data
	response := `I've analyzed your request. Here are the results:

` + "```json" + `
{
	"analysis": {
		"sentiment": "positive",
		"confidence": 0.95,
		"keywords": ["golang", "example", "documentation"]
	},
	"metadata": {
		"model": "gpt-4",
		"timestamp": "2024-01-15T10:30:00Z"
	}
}
` + "```" + `

This analysis is based on the provided context.`

	// Define the expected structure
	type Response struct {
		Analysis struct {
			Sentiment  string   `json:"sentiment"`
			Confidence float64  `json:"confidence"`
			Keywords   []string `json:"keywords"`
		} `json:"analysis"`
		Metadata struct {
			Model     string `json:"model"`
			Timestamp string `json:"timestamp"`
		} `json:"metadata"`
	}

	// Extract and unmarshal
	data, err := result.Extract[Response](response)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Sentiment: %s (%.0f%% confidence)\n",
		data.Analysis.Sentiment,
		data.Analysis.Confidence*100)
	fmt.Printf("Keywords: %v\n", data.Analysis.Keywords)

}
Output:
Sentiment: positive (95% confidence)
Keywords: [golang example documentation]
Example (ArrayResponse)

ExampleExtract_arrayResponse demonstrates extracting array responses.

package main

import (
	"fmt"
	"log"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// AI response with array of items
	response := `Here are the search results:

` + "```json" + `
[
	{"id": 1, "title": "Introduction to Go", "score": 0.98},
	{"id": 2, "title": "Advanced Go Patterns", "score": 0.85},
	{"id": 3, "title": "Go Best Practices", "score": 0.79}
]
` + "```" + `
`

	type SearchResult struct {
		ID    int     `json:"id"`
		Title string  `json:"title"`
		Score float64 `json:"score"`
	}

	results, err := result.Extract[[]SearchResult](response)
	if err != nil {
		log.Fatal(err)
	}

	for _, r := range results {
		fmt.Printf("%d. %s (score: %.2f)\n", r.ID, r.Title, r.Score)
	}

}
Output:
1. Introduction to Go (score: 0.98)
2. Advanced Go Patterns (score: 0.85)
3. Go Best Practices (score: 0.79)
Example (ComplexStructure)

ExampleExtract_complexStructure demonstrates extracting deeply nested structures.

package main

import (
	"fmt"
	"log"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// AI response with complex nested structure
	response := `Analysis complete:

` + "```json" + `
{
	"project": {
		"name": "awesome-app",
		"language": "go",
		"dependencies": {
			"direct": [
				{"name": "github.com/gorilla/mux", "version": "v1.8.0"},
				{"name": "github.com/stretchr/testify", "version": "v1.8.4"}
			],
			"indirect": 15
		},
		"metrics": {
			"lines_of_code": 5420,
			"test_coverage": 87.3,
			"complexity": {
				"average": 3.2,
				"max": 12
			}
		}
	}
}
` + "```" + `
`

	type ProjectAnalysis struct {
		Project struct {
			Name         string `json:"name"`
			Language     string `json:"language"`
			Dependencies struct {
				Direct []struct {
					Name    string `json:"name"`
					Version string `json:"version"`
				} `json:"direct"`
				Indirect int `json:"indirect"`
			} `json:"dependencies"`
			Metrics struct {
				LinesOfCode  int     `json:"lines_of_code"`
				TestCoverage float64 `json:"test_coverage"`
				Complexity   struct {
					Average float64 `json:"average"`
					Max     int     `json:"max"`
				} `json:"complexity"`
			} `json:"metrics"`
		} `json:"project"`
	}

	analysis, err := result.Extract[ProjectAnalysis](response)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Project: %s (%s)\n", analysis.Project.Name, analysis.Project.Language)
	fmt.Printf("Test Coverage: %.1f%%\n", analysis.Project.Metrics.TestCoverage)
	fmt.Printf("Direct Dependencies: %d\n", len(analysis.Project.Dependencies.Direct))

}
Output:
Project: awesome-app (go)
Test Coverage: 87.3%
Direct Dependencies: 2
Example (ErrorHandling)

ExampleExtract_errorHandling demonstrates error handling during extraction.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// Response with invalid JSON
	response := `Here's the data:

` + "```json" + `
{
	"status": "error",
	"message": "Missing closing brace"
` + "```" + `
`

	type Status struct {
		Status  string `json:"status"`
		Message string `json:"message"`
	}

	_, err := result.Extract[Status](response)
	if err != nil {
		fmt.Printf("Error: JSON parsing failed\n")
	}

}
Output:
Error: JSON parsing failed
Example (FileOperations)

ExampleExtract_fileOperations demonstrates extracting file modification instructions.

package main

import (
	"fmt"
	"log"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// AI response with file modifications
	response := `I'll fix the issue in your code:

` + "```json" + `
{
	"files": [
		{
			"filename": "main.go",
			"action": "modify",
			"content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello, World!\")\n}"
		},
		{
			"filename": "go.mod",
			"action": "create",
			"content": "module example\n\ngo 1.21"
		}
	],
	"summary": "Added missing import and created go.mod file"
}
` + "```" + `

These changes should resolve the compilation error.`

	type FileOperation struct {
		Files []struct {
			Filename string `json:"filename"`
			Action   string `json:"action"`
			Content  string `json:"content"`
		} `json:"files"`
		Summary string `json:"summary"`
	}

	ops, err := result.Extract[FileOperation](response)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Summary: %s\n", ops.Summary)
	for _, file := range ops.Files {
		fmt.Printf("- %s file: %s\n", file.Action, file.Filename)
	}

}
Output:
Summary: Added missing import and created go.mod file
- modify file: main.go
- create file: go.mod

func ExtractJSON

func ExtractJSON(responseText string) string

ExtractJSON extracts JSON content from a text response that may contain markdown code blocks. It looks for content between ```json and ``` markers, or returns the input trimmed if no markers are found.

Example

ExampleExtractJSON demonstrates extracting JSON from various markdown formats.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// Standard markdown code block
	response := `Here is the requested data:

` + "```json" + `
{
	"status": "success",
	"count": 42
}
` + "```" + `

Additional information follows.`

	json := result.ExtractJSON(response)
	fmt.Println(json)

}
Output:
{
	"status": "success",
	"count": 42
}
Example (EmptyBlock)

ExampleExtractJSON_emptyBlock demonstrates handling of empty JSON blocks.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// Empty JSON block
	response := `The operation failed.

` + "```json" + `
` + "```" + `

No data available.`

	json := result.ExtractJSON(response)
	fmt.Printf("Result: %q\n", json)

}
Output:
Result: ""
Example (MultipleBlocks)

ExampleExtractJSON_multipleBlocks demonstrates behavior with multiple JSON blocks.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// Response with multiple JSON blocks (only first is extracted)
	response := `First dataset:

` + "```json" + `
{"dataset": 1, "value": "first"}
` + "```" + `

Second dataset:

` + "```json" + `
{"dataset": 2, "value": "second"}
` + "```" + `
`

	// ExtractJSON returns the first JSON block found
	json := result.ExtractJSON(response)
	fmt.Println(json)

}
Output:
{"dataset": 1, "value": "first"}
Example (PlainJSON)

ExampleExtractJSON_plainJSON demonstrates extraction when no markdown is present.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/result"
)

func main() {
	// Plain JSON without markdown
	response := `{"message": "Hello, World!", "timestamp": 1234567890}`

	json := result.ExtractJSON(response)
	fmt.Println(json)

}
Output:
{"message": "Hello, World!", "timestamp": 1234567890}

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL