Skip to content

SDK · Go

平行映射自 TypeScript 权威实现。基于 net/http + bufio.Scanner 解析 SSE 流。

实现状态

[TODO: github.com/volo-ai/volo-go 仓库未公开。接口规格如下,可作 RFC 起点]


安装

bash
go get github.com/volo-ai/volo-go

环境要求:Go ≥ 1.21(依赖 slog、泛型)


初始化

go
package main

import (
    "context"
    "os"
    "github.com/volo-ai/volo-go"
)

func main() {
    client := volo.NewClient(&volo.Config{
        APIKey:  os.Getenv("VOLO_API_KEY"),
        BaseURL: "https://api.volo.ai",
    })
}

1 · Chat · 流式对话

go
import (
    "context"
    "fmt"
    "github.com/google/uuid"
)

ctx := context.Background()
sessionID := uuid.New()

stream, err := client.Chat.Stream(ctx, &volo.ChatRequest{
    SessionID:     sessionID,
    UserMessage:   "你好",
    ExecutionMode: volo.ModeAuto,
})
if err != nil {
    panic(err)
}
defer stream.Close()

for event := range stream.Events() {
    switch event.Type {
    case volo.EventAssistantDelta:
        fmt.Print(event.Content)
    case volo.EventToolStart:
        fmt.Printf("\n[工具] %s\n", event.ToolName)
    case volo.EventComplete:
        fmt.Println("\n[完成]")
    case volo.EventError:
        return fmt.Errorf("agent error: %s", event.Message)
    }
}

if err := stream.Err(); err != nil {
    panic(err)
}

停止 / 追加 / 恢复

go
err := client.Chat.Stop(ctx, sessionID)

err := client.Chat.Append(ctx, sessionID, "顺便加夜间模式")

resumeStream, err := client.Chat.Resume(ctx, &volo.ResumeRequest{
    TurnID:   pendingTurnID,
    Response: "选择 B 方案",
})

工具审批

go
err := client.Chat.ApproveToolCall(ctx, &volo.ToolApprovalRequest{
    ToolCallID: toolCallID,
    TurnID:     turnID,
    Approved:   true,
    Reason:     "用户已确认",
})

2 · Memory · 记忆相册

go
// 上传
file, _ := os.Open("/path/to/photo.jpg")
defer file.Close()

memory, err := client.Memory.Upload(ctx, &volo.UploadRequest{
    File:            file,
    Filename:        "photo.jpg",
    UserTitle:       "春节家宴",
    UserDescription: "2026 春节...",
})

// 列出
page, err := client.Memory.List(ctx, &volo.PageOpts{Page: 0, PageSize: 20})

// 搜索
results, err := client.Memory.Search(ctx, &volo.SearchRequest{
    Query:    "春节",
    TopK:     10,
    MinScore: 0.6,
})

// 删除
err := client.Memory.Delete(ctx, memoryID)

3 · Skill · 技能市场

go
// 列出
page, err := client.Skill.List(ctx, &volo.SkillListOpts{
    Page:     0,
    PageSize: 20,
    Category: "design",
    Keyword:  "critique",
})

// 安装 / 卸载
err := client.Skill.Install(ctx, skillID)
err := client.Skill.Uninstall(ctx, skillID)

// 我的
mine, err := client.Skill.ListMine(ctx, &volo.PageOpts{Page: 0, PageSize: 50})

// Package 子技能
children, err := client.Skill.GetChildren(ctx, packageID)
err := client.Skill.ToggleChild(ctx, packageID, childSkillID, false)

4 · Auth · 鉴权

go
result, err := client.Auth.LoginByEmail(ctx, &volo.EmailLoginRequest{
    Email: "user@example.com",
    Code:  "123456",
})

// SDK 自动 refresh
token := client.Tokens().AccessToken()

err := client.Auth.Logout(ctx)

Context 取消

所有方法接受 context.Context,取消 ctx 会立即终止请求(含 SSE 流):

go
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

stream, err := client.Chat.Stream(ctx, request)
// 30 秒后自动取消

错误处理

go
import "errors"

stream, err := client.Chat.Stream(ctx, request)
if err != nil {
    var authErr *volo.AuthError
    var rateErr *volo.RateLimitError
    var quotaErr *volo.QuotaError

    switch {
    case errors.As(err, &authErr):
        log.Fatal("API Key 无效")
    case errors.As(err, &rateErr):
        log.Printf("被限流,retry after %v", rateErr.RetryAfter)
    case errors.As(err, &quotaErr):
        log.Fatal("配额耗尽")
    default:
        log.Fatalf("未知错误: %v", err)
    }
}

类型

go
type EventType string

const (
    EventProgress       EventType = "PROGRESS"
    EventAssistantDelta EventType = "ASSISTANT_DELTA"
    EventToolStart      EventType = "TOOL_START"
    EventToolEnd        EventType = "TOOL_END"
    EventRenderUI       EventType = "RENDER_UI"
    EventInteraction    EventType = "INTERACTION"
    EventComplete       EventType = "COMPLETE"
    EventError          EventType = "ERROR"
    // ... 完整 34+ 枚举与后端镜像
)

type ExecutionMode string

const (
    ModeFast ExecutionMode = "FAST"
    ModeMax  ExecutionMode = "MAX"
    ModeAuto ExecutionMode = "AUTO"
)

与 HTTP Server 集成

把 VOLO AI 流式响应转发为 SSE:

go
http.HandleFunc("/chat", func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    var req volo.ChatRequest
    json.NewDecoder(r.Body).Decode(&req)

    stream, err := client.Chat.Stream(r.Context(), &req)
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    defer stream.Close()

    flusher := w.(http.Flusher)
    for event := range stream.Events() {
        data, _ := json.Marshal(event)
        fmt.Fprintf(w, "event: %s\ndata: %s\n\n", event.Type, data)
        flusher.Flush()
    }
})

相关

Released under the Proprietary License.