From c79add645243e0dbca8dd1f38f01ff7fe4e87552 Mon Sep 17 00:00:00 2001 From: vikingowl Date: Thu, 5 Mar 2026 20:12:02 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Phase=2010=20polish=20=E2=80=94=20packa?= =?UTF-8?q?ge=20docs,=20examples,=20integration=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add doc.go with package-level godoc for all 15 packages, runnable example functions for chat completion, streaming, embeddings, and error handling, plus build-tagged integration tests for live API validation. --- agents/doc.go | 3 ++ audio/doc.go | 5 ++ batch/doc.go | 2 + chat/doc.go | 9 ++++ classification/doc.go | 2 + conversation/doc.go | 6 +++ doc.go | 45 +++++++++++++++++ embedding/doc.go | 2 + example_test.go | 94 ++++++++++++++++++++++++++++++++++ file/doc.go | 3 ++ fim/doc.go | 3 ++ finetune/doc.go | 3 ++ integration_test.go | 115 ++++++++++++++++++++++++++++++++++++++++++ library/doc.go | 3 ++ model/doc.go | 6 +++ moderation/doc.go | 2 + ocr/doc.go | 3 ++ 17 files changed, 306 insertions(+) create mode 100644 agents/doc.go create mode 100644 audio/doc.go create mode 100644 batch/doc.go create mode 100644 chat/doc.go create mode 100644 classification/doc.go create mode 100644 conversation/doc.go create mode 100644 doc.go create mode 100644 embedding/doc.go create mode 100644 example_test.go create mode 100644 file/doc.go create mode 100644 fim/doc.go create mode 100644 finetune/doc.go create mode 100644 integration_test.go create mode 100644 library/doc.go create mode 100644 model/doc.go create mode 100644 moderation/doc.go create mode 100644 ocr/doc.go diff --git a/agents/doc.go b/agents/doc.go new file mode 100644 index 0000000..db03900 --- /dev/null +++ b/agents/doc.go @@ -0,0 +1,3 @@ +// Package agents provides types for the Mistral agents API, +// including agent CRUD operations and agent chat completions. +package agents diff --git a/audio/doc.go b/audio/doc.go new file mode 100644 index 0000000..01211b8 --- /dev/null +++ b/audio/doc.go @@ -0,0 +1,5 @@ +// Package audio provides types for the Mistral audio transcription API. +// +// Streaming transcription returns typed [StreamEvent] values via a sealed +// interface dispatched by the "type" field. +package audio diff --git a/batch/doc.go b/batch/doc.go new file mode 100644 index 0000000..6561d0c --- /dev/null +++ b/batch/doc.go @@ -0,0 +1,2 @@ +// Package batch provides types for the Mistral batch jobs API. +package batch diff --git a/chat/doc.go b/chat/doc.go new file mode 100644 index 0000000..d67554f --- /dev/null +++ b/chat/doc.go @@ -0,0 +1,9 @@ +// Package chat provides types for the Mistral chat completion API. +// +// Messages use a sealed interface pattern — create them with +// [UserMessage], [SystemMessage], [AssistantMessage], or [ToolMessage] +// struct literals. +// +// Content is polymorphic: it can be a plain string (via [TextContent]), +// nil, or a slice of [ContentChunk] values (text, image URL, document URL, audio). +package chat diff --git a/classification/doc.go b/classification/doc.go new file mode 100644 index 0000000..4744a73 --- /dev/null +++ b/classification/doc.go @@ -0,0 +1,2 @@ +// Package classification provides types for the Mistral classification API. +package classification diff --git a/conversation/doc.go b/conversation/doc.go new file mode 100644 index 0000000..4472e4d --- /dev/null +++ b/conversation/doc.go @@ -0,0 +1,6 @@ +// Package conversation provides types for the Mistral conversations API. +// +// Conversations support multi-turn interactions with start, append, and +// restart operations. Streaming returns typed [Event] values via a sealed +// interface dispatched by the "type" discriminator. +package conversation diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..2d4b520 --- /dev/null +++ b/doc.go @@ -0,0 +1,45 @@ +// Package mistral provides an idiomatic Go client for the Mistral AI API. +// +// Create a client with your API key, then call methods for each endpoint: +// +// client := mistral.NewClient("sk-...") +// +// // Chat completion +// resp, err := client.ChatComplete(ctx, &chat.CompletionRequest{ +// Model: "mistral-small-latest", +// Messages: []chat.Message{&chat.UserMessage{Content: chat.TextContent("Hello!")}}, +// }) +// +// // Streaming +// stream, err := client.ChatCompleteStream(ctx, req) +// defer stream.Close() +// for stream.Next() { +// chunk := stream.Current() +// fmt.Print(chunk.Choices[0].Delta.Content) +// } +// +// # Configuration +// +// Use functional options to configure the client: +// +// client := mistral.NewClient("sk-...", +// mistral.WithTimeout(30 * time.Second), +// mistral.WithRetry(3, 500*time.Millisecond), +// ) +// +// # Error Handling +// +// API errors are returned as *[APIError] values. Use sentinel checkers +// for common cases: +// +// if mistral.IsRateLimit(err) { +// // back off and retry +// } +// +// # Sub-packages +// +// Types are organized into sub-packages by domain: [chat], [agents], +// [conversation], [embedding], [model], [file], [finetune], [batch], +// [ocr], [audio], [library], [moderation], [classification], and [fim]. +// All service methods live directly on [Client]. +package mistral diff --git a/embedding/doc.go b/embedding/doc.go new file mode 100644 index 0000000..7c87968 --- /dev/null +++ b/embedding/doc.go @@ -0,0 +1,2 @@ +// Package embedding provides types for the Mistral embeddings API. +package embedding diff --git a/example_test.go b/example_test.go new file mode 100644 index 0000000..db0dbfe --- /dev/null +++ b/example_test.go @@ -0,0 +1,94 @@ +package mistral_test + +import ( + "context" + "fmt" + "log" + + mistral "somegit.dev/vikingowl/mistral-go-sdk" + "somegit.dev/vikingowl/mistral-go-sdk/chat" + "somegit.dev/vikingowl/mistral-go-sdk/embedding" +) + +func ExampleNewClient() { + client := mistral.NewClient("sk-your-api-key") + _ = client // use client to call API methods +} + +func ExampleClient_ChatComplete() { + client := mistral.NewClient("sk-your-api-key") + + resp, err := client.ChatComplete(context.Background(), &chat.CompletionRequest{ + Model: "mistral-small-latest", + Messages: []chat.Message{ + &chat.UserMessage{Content: chat.TextContent("What is the capital of France?")}, + }, + }) + if err != nil { + log.Fatal(err) + } + + fmt.Println(resp.Choices[0].Message.Content) +} + +func ExampleClient_ChatCompleteStream() { + client := mistral.NewClient("sk-your-api-key") + + stream, err := client.ChatCompleteStream(context.Background(), &chat.CompletionRequest{ + Model: "mistral-small-latest", + Messages: []chat.Message{ + &chat.UserMessage{Content: chat.TextContent("Tell me a short joke.")}, + }, + }) + if err != nil { + log.Fatal(err) + } + defer stream.Close() + + for stream.Next() { + chunk := stream.Current() + if len(chunk.Choices) > 0 { + fmt.Print(chunk.Choices[0].Delta.Content) + } + } + if err := stream.Err(); err != nil { + log.Fatal(err) + } +} + +func ExampleClient_CreateEmbeddings() { + client := mistral.NewClient("sk-your-api-key") + + resp, err := client.CreateEmbeddings(context.Background(), &embedding.Request{ + Model: "mistral-embed", + Input: []string{"Hello world"}, + }) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Embedding dimension: %d\n", len(resp.Data[0].Embedding)) +} + +func ExampleIsRateLimit() { + client := mistral.NewClient("sk-your-api-key") + + _, err := client.ChatComplete(context.Background(), &chat.CompletionRequest{ + Model: "mistral-small-latest", + Messages: []chat.Message{ + &chat.UserMessage{Content: chat.TextContent("Hi")}, + }, + }) + if mistral.IsRateLimit(err) { + fmt.Println("Rate limited — back off and retry") + } +} + +func ExampleIsNotFound() { + client := mistral.NewClient("sk-your-api-key") + + _, err := client.GetModel(context.Background(), "nonexistent-model") + if mistral.IsNotFound(err) { + fmt.Println("Model not found") + } +} diff --git a/file/doc.go b/file/doc.go new file mode 100644 index 0000000..336c1b3 --- /dev/null +++ b/file/doc.go @@ -0,0 +1,3 @@ +// Package file provides types for the Mistral files API, +// including upload, download, and metadata operations. +package file diff --git a/fim/doc.go b/fim/doc.go new file mode 100644 index 0000000..77c8921 --- /dev/null +++ b/fim/doc.go @@ -0,0 +1,3 @@ +// Package fim provides types for the Mistral Fill-in-the-Middle (FIM) +// completion API, used for code infilling tasks. +package fim diff --git a/finetune/doc.go b/finetune/doc.go new file mode 100644 index 0000000..1f850d3 --- /dev/null +++ b/finetune/doc.go @@ -0,0 +1,3 @@ +// Package finetune provides types for the Mistral fine-tuning API, +// including job creation, monitoring, and model archiving. +package finetune diff --git a/integration_test.go b/integration_test.go new file mode 100644 index 0000000..995877e --- /dev/null +++ b/integration_test.go @@ -0,0 +1,115 @@ +//go:build integration + +package mistral + +import ( + "context" + "os" + "strings" + "testing" + + "somegit.dev/vikingowl/mistral-go-sdk/chat" + "somegit.dev/vikingowl/mistral-go-sdk/embedding" +) + +func integrationClient(t *testing.T) *Client { + t.Helper() + key := os.Getenv("MISTRAL_API_KEY") + if key == "" { + t.Skip("MISTRAL_API_KEY not set") + } + return NewClient(key) +} + +func TestIntegration_ListModels(t *testing.T) { + client := integrationClient(t) + + resp, err := client.ListModels(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(resp.Data) == 0 { + t.Fatal("expected at least one model") + } + if resp.Data[0].ID == "" { + t.Error("expected model to have an ID") + } +} + +func TestIntegration_ChatComplete(t *testing.T) { + client := integrationClient(t) + + resp, err := client.ChatComplete(context.Background(), &chat.CompletionRequest{ + Model: "mistral-small-latest", + Messages: []chat.Message{ + &chat.UserMessage{Content: chat.TextContent("Reply with exactly: hello")}, + }, + }) + if err != nil { + t.Fatal(err) + } + + if len(resp.Choices) == 0 { + t.Fatal("no choices returned") + } + content := resp.Choices[0].Message.Content.String() + if !strings.Contains(strings.ToLower(content), "hello") { + t.Errorf("expected 'hello' in response, got %q", content) + } +} + +func TestIntegration_ChatCompleteStream(t *testing.T) { + client := integrationClient(t) + + stream, err := client.ChatCompleteStream(context.Background(), &chat.CompletionRequest{ + Model: "mistral-small-latest", + Messages: []chat.Message{ + &chat.UserMessage{Content: chat.TextContent("Say hi")}, + }, + }) + if err != nil { + t.Fatal(err) + } + defer stream.Close() + + chunks := 0 + for stream.Next() { + chunks++ + } + if err := stream.Err(); err != nil { + t.Fatal(err) + } + if chunks == 0 { + t.Error("expected at least one stream chunk") + } +} + +func TestIntegration_Embeddings(t *testing.T) { + client := integrationClient(t) + + resp, err := client.CreateEmbeddings(context.Background(), &embedding.Request{ + Model: "mistral-embed", + Input: []string{"The quick brown fox"}, + }) + if err != nil { + t.Fatal(err) + } + if len(resp.Data) != 1 { + t.Fatalf("expected 1 embedding, got %d", len(resp.Data)) + } + if len(resp.Data[0].Embedding) == 0 { + t.Error("embedding vector is empty") + } +} + +func TestIntegration_ErrorHandling(t *testing.T) { + client := integrationClient(t) + + _, err := client.GetModel(context.Background(), "definitely-not-a-real-model-id") + if err == nil { + t.Fatal("expected error for nonexistent model") + } + if !IsNotFound(err) { + t.Logf("got non-404 error (may vary by API): %v", err) + } +} diff --git a/library/doc.go b/library/doc.go new file mode 100644 index 0000000..f42f320 --- /dev/null +++ b/library/doc.go @@ -0,0 +1,3 @@ +// Package library provides types for the Mistral document libraries API, +// including library and document CRUD, sharing, and processing. +package library diff --git a/model/doc.go b/model/doc.go new file mode 100644 index 0000000..e15dd3b --- /dev/null +++ b/model/doc.go @@ -0,0 +1,6 @@ +// Package model provides types for Mistral model listing and metadata. +// +// Model cards use a sealed interface — [BaseModelCard] for platform models +// and [FTModelCard] for fine-tuned models. JSON unmarshaling dispatches on +// the "type" field. +package model diff --git a/moderation/doc.go b/moderation/doc.go new file mode 100644 index 0000000..67f4a34 --- /dev/null +++ b/moderation/doc.go @@ -0,0 +1,2 @@ +// Package moderation provides types for the Mistral moderation API. +package moderation diff --git a/ocr/doc.go b/ocr/doc.go new file mode 100644 index 0000000..18191cd --- /dev/null +++ b/ocr/doc.go @@ -0,0 +1,3 @@ +// Package ocr provides types for the Mistral OCR API, +// including document processing with page-level extraction. +package ocr