gorouter

package module
v0.0.0-...-cc5222e Latest Latest
Warning

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

Go to latest
Published: Mar 8, 2026 License: MIT Imports: 13 Imported by: 0

README

# GoRouter Kit

Go Version Go Reference Module Fork Base

Русский | English

GoRouter Kit is a production-focused Go SDK for the OpenRouter API.

The project is a Go fork inspired by openrouter-kit, rewritten for idiomatic Go and backend workloads.

Installation

go get github.com/bycmd/GoRouter-kit
import gorouter "github.com/bycmd/GoRouter-kit"

Table of Contents

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    gorouter "github.com/bycmd/GoRouter-kit"
)

func main() {
    cli, err := gorouter.New(gorouter.Config{
        APIKey: os.Getenv("OPENROUTER_API_KEY"),
        Model:  "openai/gpt-4o-mini",
    })
    if err != nil {
        log.Fatal(err)
    }
    defer cli.Destroy()

    resp, err := cli.Chat(context.Background(), gorouter.ChatRequest{
        Messages: []gorouter.Message{
            {Role: gorouter.RoleUser, Content: "Reply in one short sentence."},
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(resp.Choices[0].Message.Content)
}

Client Configuration

Required:

  • APIKey

Common options:

  • Model default model for requests
  • BaseURL custom API endpoint (default is OpenRouter v1)
  • Timeout, MaxRetries, RetryBaseDelay, RetryMaxDelay HTTP behavior
  • History storage backend for session persistence
  • ModelPrices, RefreshPricesOnUp, PriceRefreshEvery pricing control
  • Security tool-call guard
  • MaxToolCalls, ParallelToolCalls tool execution limits
cli, err := gorouter.New(gorouter.Config{
    APIKey:            os.Getenv("OPENROUTER_API_KEY"),
    Model:             "openai/gpt-4o-mini",
    Timeout:           90 * time.Second,
    MaxRetries:        3,
    RetryBaseDelay:    300 * time.Millisecond,
    RetryMaxDelay:     4 * time.Second,
    History:           gorouter.NewMemoryHistoryStore(),
    MaxToolCalls:      5,
    ParallelToolCalls: true,
})

Examples

1. Basic Chat

resp, err := cli.Chat(context.Background(), gorouter.ChatRequest{
    SessionID: "demo",
    Messages: []gorouter.Message{
        {Role: gorouter.RoleUser, Content: "Summarize this in one sentence."},
    },
})
if err != nil {
    log.Fatal(err)
}
fmt.Println(resp.Choices[0].Message.Content)

2. Ask API with Automatic Session Keys

Ask composes messages from prompt options and can build session keys from User and Group.

resp, err := cli.Ask(context.Background(), gorouter.ChatOptions{
    User:         "u-42",
    Group:        "team-a",
    SystemPrompt: "You are concise.",
    Prompt:       "Explain what retry with exponential backoff means.",
    Request: gorouter.ChatRequest{
        Model: "openai/gpt-4o-mini",
    },
})
if err != nil {
    log.Fatal(err)
}
fmt.Println(resp.Choices[0].Message.Content)

3. Streaming Output

result, err := cli.ChatStreamResult(context.Background(), gorouter.ChatRequest{
    Messages: []gorouter.Message{
        {Role: gorouter.RoleUser, Content: "Stream a short answer."},
    },
}, &gorouter.StreamCallbacks{
    OnContent: func(part string) {
        fmt.Print(part)
    },
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("\nmodel=%s finish=%s duration_ms=%d\n", result.Model, result.FinishReason, result.DurationMs)

4. Structured Output with json_object

resp, err := cli.Chat(context.Background(), gorouter.ChatRequest{
    Messages: []gorouter.Message{
        {Role: gorouter.RoleUser, Content: "Return JSON with fields title and score."},
    },
    ResponseFormat: &gorouter.ResponseFormat{
        Type: "json_object",
    },
})
if err != nil {
    log.Fatal(err)
}

var out map[string]any
if err := json.Unmarshal([]byte(resp.Choices[0].Message.Content), &out); err != nil {
    log.Fatal(err)
}
fmt.Println(out)

5. Structured Output with json_schema

resp, err := cli.Chat(context.Background(), gorouter.ChatRequest{
    Messages: []gorouter.Message{
        {Role: gorouter.RoleUser, Content: "Return JSON summary for user Alice with age and city."},
    },
    ResponseFormat: &gorouter.ResponseFormat{
        Type: "json_schema",
        JSONSchema: &gorouter.ResponseJSONSchema{
            Name:   "user_summary",
            Strict: true,
            Schema: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "name": map[string]any{"type": "string"},
                    "age":  map[string]any{"type": "integer"},
                    "city": map[string]any{"type": "string"},
                },
                "required": []string{"name", "age", "city"},
            },
        },
    },
})
if err != nil {
    log.Fatal(err)
}

var out map[string]any
if err := json.Unmarshal([]byte(resp.Choices[0].Message.Content), &out); err != nil {
    log.Fatal(err)
}
fmt.Println(out)

6. Tool Calling with Execution Report

params, _ := json.Marshal(map[string]any{
    "type": "object",
    "properties": map[string]any{
        "a": map[string]any{"type": "number"},
        "b": map[string]any{"type": "number"},
    },
    "required": []string{"a", "b"},
})

report, err := cli.ChatWithReport(context.Background(), gorouter.ChatRequest{
    Messages: []gorouter.Message{
        {Role: gorouter.RoleUser, Content: "Use tool sum for 7 and 5, then answer."},
    },
    Tools: []gorouter.Tool{
        {
            Type: "function",
            Function: gorouter.ToolFunction{
                Name:       "sum",
                Description: "Adds two numbers",
                Parameters: params,
            },
            Execute: func(ctx context.Context, args any, call gorouter.ToolCall) (any, error) {
                m, _ := args.(map[string]any)
                a, _ := m["a"].(float64)
                b, _ := m["b"].(float64)
                return map[string]any{"value": a + b}, nil
            },
        },
    },
    IncludeToolResultInReport: true,
})
if err != nil {
    log.Fatal(err)
}

for _, c := range report.ToolCalls {
    fmt.Printf("tool=%s status=%s duration_ms=%d\n", c.ToolName, c.Status, c.DurationMs)
}

7. Service API Methods

models, err := cli.GetModels(context.Background())
if err != nil {
    log.Fatal(err)
}

keyInfo, err := cli.GetAPIKeyInfo(context.Background())
if err != nil {
    log.Fatal(err)
}

balance, err := cli.GetCreditBalance(context.Background())
if err != nil {
    log.Fatal(err)
}

fmt.Println(len(models), keyInfo.Data.RateLimit.Interval, balance.TotalCredits)

8. Pricing Refresh and Cost Snapshot

if err := cli.RefreshModelPrices(context.Background()); err != nil {
    log.Fatal(err)
}

cli.StartPriceAutoRefresh(context.Background(), 6*time.Hour)
defer cli.StopPriceAutoRefresh()

snap := cli.CostSnapshot()
fmt.Println(snap.TotalCost)

price, ok := cli.ModelPrice("openai/gpt-4o-mini")
fmt.Println(ok, price)

9. Plugins

if err := cli.RegisterPlugin(gorouter.NewLoggingPlugin()); err != nil {
    log.Fatal(err)
}

metrics := gorouter.NewMetricsPlugin()
if err := cli.RegisterPlugin(metrics); err != nil {
    log.Fatal(err)
}

billing := gorouter.NewBillingPlugin(gorouter.BillingPluginOptions{
    Reporter: func(ctx context.Context, report gorouter.BillingReport) error {
        fmt.Printf("model=%s tokens=%d cost=%.6f\n", report.Model, report.Usage.TotalTokens, report.Cost)
        return nil
    },
})
if err := cli.RegisterPlugin(billing); err != nil {
    log.Fatal(err)
}

fmt.Printf("metrics=%+v\n", metrics.Snapshot())

10. History Adapters and Analyzer

store := gorouter.NewMemoryHistoryStore()
cli.SetHistoryStore(store)

disk := gorouter.NewDiskHistoryStore(".gorouter-history")
cli.SetHistoryStore(disk)

manager := gorouter.NewHistoryManager(gorouter.NewMemoryHistoryStore(), gorouter.HistoryManagerOptions{
    TTL:             30 * time.Minute,
    CleanupInterval: 5 * time.Minute,
})
defer manager.Destroy()

analyzer := gorouter.NewHistoryAnalyzer(manager)
stats, err := analyzer.GetStats(context.Background(), "user:42", gorouter.HistoryQueryOptions{})
if err != nil {
    log.Fatal(err)
}
fmt.Println(stats.TotalAPICalls, stats.TotalCost)

11. Security Guard for Tool Calls

allow := true

guard := gorouter.NewSecurityManager(gorouter.SecurityConfig{
    DefaultPolicy:         "deny-all",
    RequireAuthentication: true,
    Auth: gorouter.SecurityAuthConfig{
        Type: gorouter.SecurityAuthTypeAPIKey,
        APIKeys: map[string]gorouter.SecurityUser{
            "demo-token": {
                ID:     "u-1",
                Roles:  []string{"user"},
                Scopes: []string{"tools:run"},
            },
        },
    },
    Tools: map[string]gorouter.SecurityToolPolicy{
        "sum": {
            Allow:  &allow,
            Scopes: []string{"tools:run"},
        },
    },
})

cli.SetSecurityGuard(guard)

Error Handling

resp, err := cli.Chat(context.Background(), req)
if err != nil {
    var apiErr *gorouter.APIError
    if errors.As(err, &apiErr) {
        log.Printf("api error: status=%d message=%s", apiErr.StatusCode, apiErr.Message)
        return
    }
    if errors.Is(err, gorouter.ErrBadRequest) {
        log.Printf("bad request: %v", err)
        return
    }
    log.Printf("unexpected error: %v", err)
    return
}

_ = resp

License

MIT

Documentation

Index

Constants

View Source
const (
	RoleSystem    = schema.RoleSystem
	RoleUser      = schema.RoleUser
	RoleAssistant = schema.RoleAssistant
	RoleTool      = schema.RoleTool
)
View Source
const (
	ToolRegistryOverride = pluginpack.ToolRegistryOverride
	ToolRegistryMerge    = pluginpack.ToolRegistryMerge
	ToolRegistryIfEmpty  = pluginpack.ToolRegistryIfEmpty
)
View Source
const (
	SecurityAuthTypeAPIKey = security.AuthTypeAPIKey
	SecurityAuthTypeJWT    = security.AuthTypeJWT
	SecurityAuthTypeCustom = security.AuthTypeCustom
)

Variables

View Source
var ErrAccessDenied = security.ErrAccessDenied
View Source
var ErrAuthRequired = security.ErrAuthRequired
View Source
var ErrBadRequest = errs.ErrBadRequest
View Source
var ErrDangerousArgument = security.ErrDangerousArgument
View Source
var ErrDecode = errs.ErrDecode
View Source
var ErrInvalidToken = security.ErrInvalidToken
View Source
var ErrRateLimited = security.ErrRateLimited

Functions

func NewSecurityManager

func NewSecurityManager(cfg SecurityConfig) *security.Manager

func NewSimpleGuard

func NewSimpleGuard() *security.SimpleGuard

Types

type APIError

type APIError = errs.APIError

type APIKeyInfo

type APIKeyInfo = schema.APIKeyInfo

type ApiCallMetadata

type ApiCallMetadata = history.ApiCallMetadata

type BillingPlugin

type BillingPlugin = pluginpack.BillingPlugin

func NewBillingPlugin

func NewBillingPlugin(opts BillingPluginOptions) *BillingPlugin

type BillingPluginOptions

type BillingPluginOptions = pluginpack.BillingPluginOptions

type BillingReport

type BillingReport = pluginpack.BillingReport

type BillingReporter

type BillingReporter = pluginpack.BillingReporter

type ChatOptions

type ChatOptions = schema.ChatOptions

type ChatRequest

type ChatRequest = schema.ChatRequest

type ChatResponse

type ChatResponse = schema.ChatResponse

type ChatResult

type ChatResult = schema.ChatResult

type ChatStreamChunk

type ChatStreamChunk = schema.ChatStreamChunk

type ChatStreamResult

type ChatStreamResult = schema.ChatStreamResult

type Choice

type Choice = schema.Choice

type Client

type Client = client.Client

func New

func New(cfg Config) (*Client, error)

type ClientEventHandler

type ClientEventHandler = client.EventHandler

type Config

type Config = config.Config

type CostSnapshot

type CostSnapshot = cost.Snapshot

type CostTracker

type CostTracker = cost.Tracker

func NewCostTracker

func NewCostTracker(prices PriceTable) *CostTracker

type CreditBalance

type CreditBalance = schema.CreditBalance

type DiskHistoryStore

type DiskHistoryStore = historydisk.Store

func NewDiskHistoryStore

func NewDiskHistoryStore(dir string) *DiskHistoryStore

type ExternalSecurityPlugin

type ExternalSecurityPlugin = pluginpack.ExternalSecurityPlugin

func NewExternalSecurityPlugin

func NewExternalSecurityPlugin(guard SecurityGuard) *ExternalSecurityPlugin

func NewExternalSecurityPluginWithFactory

func NewExternalSecurityPluginWithFactory(factory GuardFactory) *ExternalSecurityPlugin

type GuardFactory

type GuardFactory = pluginpack.GuardFactory

type HistoryAnalyzer

type HistoryAnalyzer = history.Analyzer

func NewHistoryAnalyzer

func NewHistoryAnalyzer(manager *HistoryManager) *HistoryAnalyzer

type HistoryEntry

type HistoryEntry = history.HistoryEntry

type HistoryEntryStore

type HistoryEntryStore = history.EntryStore

type HistoryManager

type HistoryManager = history.Manager

func NewHistoryManager

func NewHistoryManager(store HistoryEntryStore, opts HistoryManagerOptions) *HistoryManager

type HistoryManagerOptions

type HistoryManagerOptions = history.ManagerOptions

type HistoryQueryOptions

type HistoryQueryOptions = history.QueryOptions

type HistoryStats

type HistoryStats = history.Stats

type HistoryStore

type HistoryStore = history.Store

type HistoryTimeSeriesPoint

type HistoryTimeSeriesPoint = history.TimeSeriesPoint

type Hook

type Hook = hooks.Hook

type HookFunc

type HookFunc = hooks.Func

type LoggingPlugin

type LoggingPlugin = pluginpack.LoggingPlugin

func NewLoggingPlugin

func NewLoggingPlugin() *LoggingPlugin

func NewLoggingPluginWithLogger

func NewLoggingPluginWithLogger(logger *log.Logger) *LoggingPlugin

type MemoryHistoryStore

type MemoryHistoryStore = historymemory.Store

func NewMemoryHistoryStore

func NewMemoryHistoryStore() *MemoryHistoryStore

type Message

type Message = schema.Message

type MessageDelta

type MessageDelta = schema.MessageDelta

type Metrics

type Metrics = pluginpack.Metrics

type MetricsPlugin

type MetricsPlugin = pluginpack.MetricsPlugin

func NewMetricsPlugin

func NewMetricsPlugin() *MetricsPlugin

type Middleware

type Middleware = client.Middleware

type MiddlewareContext

type MiddlewareContext = client.MiddlewareContext

type ModelCost

type ModelCost = cost.ModelCost

type ModelInfo

type ModelInfo = schema.ModelInfo

type Plugin

type Plugin = client.Plugin

type Price

type Price = cost.Price

type PriceTable

type PriceTable = cost.PriceTable

type Provider

type Provider = schema.Provider

type Reasoning

type Reasoning = schema.Reasoning

type RedisHistoryPlugin

type RedisHistoryPlugin = pluginpack.RedisHistoryPlugin

func NewRedisHistoryPlugin

func NewRedisHistoryPlugin(store HistoryStore) *RedisHistoryPlugin

func NewRedisHistoryPluginFromClient

func NewRedisHistoryPluginFromClient(redisClient RedisHistoryStoreClient, opts RedisHistoryPluginOptions) *RedisHistoryPlugin

type RedisHistoryPluginOptions

type RedisHistoryPluginOptions = pluginpack.RedisHistoryPluginOptions

type RedisHistoryStore

type RedisHistoryStore = historyredis.Store

type RedisHistoryStoreClient

type RedisHistoryStoreClient = historyredis.Client

type RedisHistoryStoreOptions

type RedisHistoryStoreOptions = historyredis.Options

type ResponseFormat

type ResponseFormat = schema.ResponseFormat

type ResponseJSONSchema

type ResponseJSONSchema = schema.ResponseJSONSchema

type Role

type Role = schema.Role

type SecurityAuthConfig

type SecurityAuthConfig = security.AuthConfig

type SecurityAuthType

type SecurityAuthType = security.AuthType

type SecurityAuthenticator

type SecurityAuthenticator = security.Authenticator

type SecurityConfig

type SecurityConfig = security.Config

type SecurityDangerousArgumentsConfig

type SecurityDangerousArgumentsConfig = security.DangerousArgumentsConfig

type SecurityEventHandler

type SecurityEventHandler = security.EventHandler

type SecurityGuard

type SecurityGuard = security.Guard

type SecurityManager

type SecurityManager = security.Manager

type SecurityRateLimit

type SecurityRateLimit = security.RateLimit

type SecurityRolePolicy

type SecurityRolePolicy = security.RolePolicy

type SecurityToolCallEvent

type SecurityToolCallEvent = security.ToolCallEvent

type SecurityToolPolicy

type SecurityToolPolicy = security.ToolPolicy

type SecurityUser

type SecurityUser = security.User

type StreamCallbacks

type StreamCallbacks = schema.StreamCallbacks

type StreamChoiceChunk

type StreamChoiceChunk = schema.StreamChoiceChunk

type StreamEvent

type StreamEvent = schema.StreamEvent

type Tool

type Tool = schema.Tool

type ToolCall

type ToolCall = schema.ToolCall

type ToolCallDetail

type ToolCallDetail = schema.ToolCallDetail

type ToolCallError

type ToolCallError = schema.ToolCallError

type ToolCallFunction

type ToolCallFunction = schema.ToolCallFunction

type ToolCallOutcome

type ToolCallOutcome = schema.ToolCallOutcome

type ToolCallStatus

type ToolCallStatus = schema.ToolCallStatus

type ToolFunction

type ToolFunction = schema.ToolFunction

type ToolProvider

type ToolProvider = pluginpack.ToolProvider

type ToolRegistryMode

type ToolRegistryMode = pluginpack.ToolRegistryMode

type ToolRegistryOptions

type ToolRegistryOptions = pluginpack.ToolRegistryOptions

type ToolRegistryPlugin

type ToolRegistryPlugin = pluginpack.ToolRegistryPlugin

func NewDynamicToolRegistryPlugin

func NewDynamicToolRegistryPlugin(provider ToolProvider, opts ToolRegistryOptions) *ToolRegistryPlugin

func NewToolRegistryPlugin

func NewToolRegistryPlugin(tools []Tool, opts ToolRegistryOptions) *ToolRegistryPlugin

type ToolSecurity

type ToolSecurity = schema.ToolSecurity

type Usage

type Usage = schema.Usage

Directories

Path Synopsis
examples
basic command
history command
plugins command

Jump to

Keyboard shortcuts

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