joytoken

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Sep 2, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

JoyToken SDK for Go

English | 简体中文

First-party Go client for JoyToken's public developer API.

The module is distributed directly from GitHub and does not require a separate package-registry publication.

go get github.com/jd-opensource/joytoken-sdk-go

The default endpoint is https://api.joytokens.ai. Set JOY_TOKEN_API_BASE_URL (or pass WithAPIBaseURL) to use another environment. Requests time out after 60 seconds by default; pass WithTimeout(0) to disable that limit.

client := joytoken.NewClient(
    joytoken.WithAPIKey(os.Getenv("JOY_TOKEN_API_KEY")),
)

completion, err := client.CreateChatCompletion(ctx, joytoken.ChatCompletionRequest{
    Model: joytoken.ModelAuto,
    Messages: []joytoken.ChatMessage{
        {Role: "user", Content: "Say hello"},
    },
})
// completion is *ChatCompletionResponse (single-shot).
// Use RunChatCompletion to run the tool loop and read the RunChatResult instead.

OpenAI Responses:

CreateResponse uses the gateway's native Responses endpoint, preserving Responses tools, output items, usage, annotations, and streaming events.

result, err := client.CreateResponse(ctx, joytoken.ResponseRequest{
    Model: joytoken.ModelAuto,
    Input: "Say hello",
})
if err != nil {
    return err
}
fmt.Println(result.OutputText())

OpenAI Images:

image, err := client.GenerateImage(ctx, joytoken.ImageGenerationRequest{
    Model:  joytoken.ModelAuto,
    Prompt: "A neon JoyToken logo on a black background",
    Size:   "1024x1024",
})
if err != nil {
    return err
}
fmt.Println(image.Data[0].URL)

Edit an existing image (single URL/base64 data URI, or an array of them):

edited, err := client.EditImage(ctx, joytoken.ImageEditRequest{
    Model:  joytoken.ModelAuto,
    Prompt: "Replace the background with a starry sky and keep the subject",
    Image:  "https://picsum.photos/512/512",
})
if err != nil {
    return err
}
fmt.Println(edited.Data[0].B64JSON)

Anthropic Messages:

CreateMessage is also a local protocol adapter over the single Chat Completions gateway endpoint.

message, err := client.CreateMessage(ctx, joytoken.MessageRequest{
    Model:     joytoken.ModelAuto,
    MaxTokens: 1024,
    Messages: []joytoken.MessageParam{
        {Role: "user", Content: "Say hello"},
    },
})

The client supports:

  • POST /openai/v1/chat/completions
  • streaming chat completions via SSE
  • POST /openai/v1/responses and native Responses SSE
  • POST /openai/v1/images/generations
  • POST /openai/v1/images/edits
  • Anthropic Messages-compatible request/response and streaming adapters
  • GET /api/v1/models
  • GET /api/v1/models/meta
  • GET /api/v1/pricing

All model requests require joytoken.ModelAuto; concrete model IDs are not accepted.

Model descriptions can be localized with ListModelsWithOptions. Locale accepts joytoken.ModelLocaleZH or joytoken.ModelLocaleEN; when omitted, the API defaults to English.

models, err := client.ListModelsWithOptions(ctx, joytoken.ListModelsOptions{
    Locale: joytoken.ModelLocaleZH,
})

The SDK preserves the API response envelope; catalog entries are available at models.Data.Models.

The agent subpackage provides the same bounded tool-calling loop as the TypeScript Agent SDK:

go get github.com/jd-opensource/joytoken-sdk-go/agent
import (
    "context"
    "os"

    joytoken "github.com/jd-opensource/joytoken-sdk-go"
    "github.com/jd-opensource/joytoken-sdk-go/agent"
)

ctx := context.Background()
client := joytoken.NewClient(joytoken.WithAPIKey(os.Getenv("JOY_TOKEN_API_KEY")))
provider := agent.NewJoyTokenProvider(client)
runner := agent.New(agent.AgentOptions{
    Model: provider,
    Tools: []agent.AgentTool{{
        Name: "lookup",
        Execute: func(ctx context.Context, input any, execution agent.ToolExecutionContext) (any, error) {
            return "record:42", nil
        },
    }},
})
result, err := runner.Run(ctx, "Summarize record 42")

Every run has a hard eight-step limit by default. Use RunWithOptions with MaxSteps: agent.Int(6) or add StepCountIs, MaxToolCalls, and MaxCost conditions.

Prefer a ready-made, safe tool set with built-in permissions and middleware? Use toolkit.NewAgent(...) for zero-config defaults, or register host-configured tools (file/HTTP/SQL) with an approval callback. See agent/README.md.

Streaming

Streaming supports tool execution too. There are two levels:

  • StreamChatCompletion, StreamResponse, and StreamMessage are raw streams that never execute caller-owned tools.
  • RunChatCompletionStream, RunResponseStream, and RunMessageStream stream text via OnTextDelta and execute matching tools between turns until the loop stops.

Opaque provider tool metadata is retained in ToolCall.ExtraContent and round-tripped by every Run* loop plus the Messages and Responses adapters. For example, Gemini's extra_content.google.thought_signature survives local tool execution. A manual loop should append the complete returned ToolCall instead of rebuilding only its id and function fields.

Raw stream primitive (no tool execution):

stream, err := client.StreamChatCompletion(ctx, joytoken.ChatCompletionRequest{
    Model: joytoken.ModelAuto,
    Messages: []joytoken.ChatMessage{{Role: "user", Content: "Say hello"}},
})
if err != nil {
    return err
}
defer stream.Close()

for {
    chunk, err := stream.Recv()
    if errors.Is(err, io.EOF) {
        break
    }
    if err != nil {
        return err
    }
	for _, choice := range chunk.Choices {
		if text, ok := choice.Delta["content"].(string); ok {
			fmt.Print(text)
		}
	}
}

The Gateway may emit a metadata/usage-only SSE event with no choices. The SDK preserves that event and normalizes chunk.Choices to an empty slice, so range and len(chunk.Choices) are safe. Never index chunk.Choices[0] without a length check. When protocol-level usage is absent, the SDK derives token counts from metadata.billing; explicit protocol usage remains authoritative.

Use response.RequestID(), chunk.RequestID(), or joytoken.RequestIDFromMetadata(metadata) to read the request ID. These helpers prefer response metadata and also accept a successful HTTP request-ID header when one is available.

StreamMessage exposes the same raw iterator pattern for Anthropic Messages; use RunMessageStream for its streaming tool loop. Always close a raw stream when the consumer stops early.

Errors

Authenticated model calls, model metadata and pricing requests return joytoken.ErrMissingAPIKey before sending a network request when no API key is configured. ListModels remains the unauthenticated catalog call.

HTTP failures are returned as *joytoken.APIError. Use joytoken.IsAPIError(err) or errors.As to inspect the status code, request ID, response headers, and parsed response body. The Agent package returns provider and tool errors to the caller without hiding them.

Explicit Run* methods return the partial result together with an error when a model request or local execution fails. The partial result uses StoppedBy == "error"; inspect Steps and the accumulated Messages or Input to retain already completed tool work and diagnostics. StoppedBy == "max_steps" is reserved for a loop that actually exhausts its configured step limit. For Chat runs, FinishReason is also "error" on this path.

Validate

go test ./...

cd example
go test ./...

Live example

cd example
export JOY_TOKEN_API_KEY="..."
go run ./live

Contributing

See CONTRIBUTING.md, SECURITY.md, and CODE_OF_CONDUCT.md.

Documentation

Overview

Package joytoken provides a Go client for the JoyToken API.

It supports the gateway's native OpenAI-compatible Chat Completions and Responses endpoints plus a local Anthropic Messages adapter.

Index

Constants

View Source
const (
	// OrchestrationPlannerTaskID is the task id of the planning step.
	OrchestrationPlannerTaskID = "__planner__"
	// OrchestrationFinalTaskID is the task id of the aggregated final answer.
	OrchestrationFinalTaskID = "__final__"
	// OrchestrationPhasePlanning is the orchestration phase value emitted while
	// the plan is being produced.
	OrchestrationPhasePlanning = "planning"
)

Well-known orchestration task identifiers surfaced by the Gateway. The planner entry carries the plan (seq 0); the final entry carries the aggregated answer.

View Source
const ModelAuto = "auto"

ModelAuto is the only model value accepted by JoyToken requests.

Variables

View Source
var ErrMissingAPIKey = errors.New("joytoken API key is required; pass WithAPIKey or set JOY_TOKEN_API_KEY")

ErrMissingAPIKey is returned when an authenticated endpoint is called without configuring a JoyToken API key.

Functions

func IsAPIError

func IsAPIError(err error) bool

IsAPIError reports whether err contains an APIError.

func RequestIDFromMetadata added in v0.1.2

func RequestIDFromMetadata(metadata map[string]any) string

RequestIDFromMetadata returns the Gateway request ID carried in a response metadata object. JoyToken includes this body-level fallback even when an upstream response does not provide a request ID header.

Types

type APIError

type APIError struct {
	StatusCode      int
	Code            ErrorCode
	RequestID       string
	ResponseHeaders http.Header
	Body            any
}

APIError describes a non-successful JoyToken HTTP response.

func (*APIError) Error

func (e *APIError) Error() string

Error returns a readable API failure description.

type CatalogOption

type CatalogOption struct {
	Value string `json:"value"`
	Label string `json:"label"`
}

CatalogOption is a value-label pair used by model catalog filters.

type ChatCompletionChoice

type ChatCompletionChoice struct {
	Index        int         `json:"index"`
	Message      ChatMessage `json:"message"`
	FinishReason string      `json:"finish_reason,omitempty"`
	Logprobs     any         `json:"logprobs,omitempty"`
}

ChatCompletionChoice is one generated completion choice.

type ChatCompletionChunk

type ChatCompletionChunk struct {
	ID       string                      `json:"id,omitempty"`
	Object   string                      `json:"object,omitempty"`
	Created  int64                       `json:"created,omitempty"`
	Model    string                      `json:"model,omitempty"`
	Choices  []ChatCompletionChunkChoice `json:"choices"`
	Usage    *Usage                      `json:"usage,omitempty"`
	Metadata map[string]any              `json:"metadata,omitempty"`

	// Error carries the Gateway error envelope when a streaming event reports a
	// failure ({"error":{...}}). It is nil for a normal delta/metadata event.
	// The SDK detects this envelope on Recv and surfaces it as an *APIError.
	Error map[string]any `json:"error,omitempty"`

	// Orchestration carries the Gateway orchestration progress for this event
	// when present: the planning phase and plan, or the executing sub-task's
	// id/seq/status/title. It is nil for a non-orchestrated stream.
	Orchestration *ChunkOrchestration `json:"orchestration,omitempty"`

	// MetadataList holds the full per-sub-task metadata array when the chunk's
	// metadata arrives as an array. It is nil otherwise. Metadata remains the
	// canonical marshaled field.
	MetadataList []OrchestrationTaskMeta `json:"-"`
}

ChatCompletionChunk is one streaming completion event. Gateway metadata and usage events may have an empty Choices slice; callers must check len(Choices) or range over it instead of indexing Choices[0] unconditionally.

When Gateway orchestration is engaged, a chunk may carry a top-level "orchestration" object describing either the planning phase (with the full plan) or the currently executing sub-task (task id/seq/status/title). The "metadata" field may also arrive as a per-sub-task array; MetadataList exposes it while Metadata keeps the first/primary object for existing code.

func (*ChatCompletionChunk) RequestID added in v0.1.2

func (c *ChatCompletionChunk) RequestID() string

RequestID returns the Gateway request ID carried by this stream event.

func (*ChatCompletionChunk) UnmarshalJSON added in v0.1.5

func (c *ChatCompletionChunk) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a streaming chunk, tolerating the orchestration object and an array-shaped metadata field. Non-orchestrated bytes decode as before.

type ChatCompletionChunkChoice

type ChatCompletionChunkChoice struct {
	Index        int            `json:"index"`
	Delta        map[string]any `json:"delta"`
	FinishReason string         `json:"finish_reason,omitempty"`
	Logprobs     any            `json:"logprobs,omitempty"`
}

ChatCompletionChunkChoice is one incremental streaming choice.

type ChatCompletionRequest

type ChatCompletionRequest struct {
	Model       string         `json:"model"`
	Messages    []ChatMessage  `json:"messages"`
	Stream      bool           `json:"stream,omitempty"`
	Temperature *float64       `json:"temperature,omitempty"`
	MaxTokens   *int           `json:"max_tokens,omitempty"`
	TopP        *float64       `json:"top_p,omitempty"`
	Stop        any            `json:"stop,omitempty"`
	Tools       []ChatTool     `json:"tools"`
	ToolChoice  any            `json:"tool_choice,omitempty"`
	Tier        string         `json:"tier,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
}

ChatCompletionRequest is an OpenAI-compatible completion request. Model must be ModelAuto.

type ChatCompletionResponse

type ChatCompletionResponse struct {
	ID       string                 `json:"id,omitempty"`
	Object   string                 `json:"object,omitempty"`
	Created  int64                  `json:"created,omitempty"`
	Model    string                 `json:"model,omitempty"`
	Choices  []ChatCompletionChoice `json:"choices"`
	Usage    *Usage                 `json:"usage,omitempty"`
	Metadata map[string]any         `json:"metadata,omitempty"`

	// Error carries the Gateway error envelope when a request answered HTTP 200
	// but the body reported a failure (for example a failed orchestration run:
	// {"error":{...},"choices":[]}). It is nil for a successful completion. The
	// SDK detects this envelope and surfaces it as an *APIError rather than
	// returning an empty response.
	Error map[string]any `json:"error,omitempty"`

	// MetadataList holds the full per-sub-task metadata array when Gateway
	// orchestration is engaged. It is nil for a plain completion. It is not
	// serialized directly; Metadata remains the canonical marshaled field.
	MetadataList []OrchestrationTaskMeta `json:"-"`

	// Plan lists the orchestrator's planned sub-tasks when present.
	Plan []PlanEntry `json:"plan,omitempty"`
}

ChatCompletionResponse is a non-streaming completion response.

When Gateway orchestration is engaged, the wire "metadata" field is a JSON array (one entry per orchestrated sub-task) rather than a single object, and a top-level "plan" array describes the planned sub-tasks. The custom UnmarshalJSON keeps Metadata populated with the first/primary object so existing code that reads Metadata keeps working, while MetadataList exposes the full per-task array and Plan exposes the plan. For a plain (non-orchestrated) response the bytes decode exactly as before.

func (*ChatCompletionResponse) IsOrchestrated added in v0.1.5

func (r *ChatCompletionResponse) IsOrchestrated() bool

IsOrchestrated reports whether this response carries Gateway orchestration output (a per-sub-task metadata array).

func (*ChatCompletionResponse) RequestID added in v0.1.2

func (r *ChatCompletionResponse) RequestID() string

RequestID returns the Gateway request ID carried in response metadata. The SDK also copies a successful HTTP request ID header here when one is present.

func (*ChatCompletionResponse) UnmarshalJSON added in v0.1.5

func (r *ChatCompletionResponse) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a completion, tolerating a "metadata" field that is either a single object (plain response) or a per-sub-task array (Gateway orchestration). Non-orchestrated bytes decode identically to the default.

type ChatCompletionStream

type ChatCompletionStream struct {
	// contains filtered or unexported fields
}

ChatCompletionStream reads Chat Completions SSE events.

func (*ChatCompletionStream) Close

func (s *ChatCompletionStream) Close() error

Close closes the underlying streaming response body.

func (*ChatCompletionStream) Recv

Recv returns the next completion chunk or io.EOF when the stream ends.

type ChatMessage

type ChatMessage = tooldef.ChatMessage

ChatMessage is an OpenAI-compatible conversation message.

type ChatTool

type ChatTool = tooldef.ChatTool

ChatTool declares a tool available to Chat Completions.

type ChatToolFunction

type ChatToolFunction = tooldef.ChatToolFunction

ChatToolFunction contains the schema for a callable function.

type ChunkOrchestration added in v0.1.5

type ChunkOrchestration struct {
	Phase      string      `json:"phase,omitempty"`
	Plan       []PlanEntry `json:"plan,omitempty"`
	TaskID     string      `json:"task_id,omitempty"`
	TaskSeq    int         `json:"task_seq,omitempty"`
	TaskStatus string      `json:"task_status,omitempty"`
	Title      string      `json:"title,omitempty"`
}

ChunkOrchestration is the top-level "orchestration" object on a streaming chunk. During planning it carries Phase and Plan; during execution it carries the currently running sub-task's identity and status.

func (*ChunkOrchestration) IsPlanning added in v0.1.5

func (o *ChunkOrchestration) IsPlanning() bool

IsPlanning reports whether this chunk orchestration event carries the plan.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a reusable, concurrency-safe JoyToken API client.

func NewClient

func NewClient(opts ...Option) *Client

NewClient creates a JoyToken client from environment defaults and options.

func (*Client) CreateChatCompletion

func (c *Client) CreateChatCompletion(ctx context.Context, request ChatCompletionRequest) (*ChatCompletionResponse, error)

CreateChatCompletion sends an OpenAI-compatible Chat Completions request to the gateway's single model endpoint. Request-level tools, including an explicitly empty slice, are forwarded unchanged. Tools registered with WithTools are also user-owned and are forwarded without automatic execution. Only when the caller supplied no tools at either level does the client inject and execute its default fallback tools.

func (*Client) CreateMessage

func (c *Client) CreateMessage(ctx context.Context, request MessageRequest) (*MessageResponse, error)

CreateMessage exposes Anthropic Messages semantics over the gateway's single Chat Completions endpoint.

func (*Client) CreateResponse

func (c *Client) CreateResponse(ctx context.Context, request ResponseRequest) (*Response, error)

CreateResponse sends an OpenAI Responses-compatible request to the gateway's native Responses endpoint. User-owned tools remain primitive; only the SDK fallback set auto-runs when no request-level or registered tools exist.

func (*Client) EditImage added in v0.2.1

func (c *Client) EditImage(ctx context.Context, request ImageEditRequest) (*ImageGenerationResponse, error)

EditImage edits one or more source images using an OpenAI-compatible request. Prompt and Image are required; Image is a single URL/base64 data URI (string) or multiple of them ([]string). When Model is set it must be ModelAuto.

func (*Client) GenerateImage

func (c *Client) GenerateImage(ctx context.Context, request ImageGenerationRequest) (*ImageGenerationResponse, error)

GenerateImage creates an OpenAI-compatible image generation.

func (*Client) GetModelMeta

func (c *Client) GetModelMeta(ctx context.Context) (*ModelMetadataResponse, error)

GetModelMeta returns filter metadata for the model catalog.

func (*Client) GetPricing

func (c *Client) GetPricing(ctx context.Context) (*PricingResponse, error)

GetPricing returns the current JoyToken pricing catalog.

func (*Client) ListModels

func (c *Client) ListModels(ctx context.Context) (*ModelListResponse, error)

ListModels lists the public JoyToken model catalog.

func (*Client) ListModelsWithOptions

func (c *Client) ListModelsWithOptions(ctx context.Context, options ListModelsOptions) (*ModelListResponse, error)

ListModelsWithOptions lists the public JoyToken model catalog with optional response localization. When Locale is empty, the API defaults to English.

func (*Client) RunChatCompletion added in v0.1.1

func (c *Client) RunChatCompletion(ctx context.Context, request ChatCompletionRequest, opts RunChatOptions) (*RunChatResult, error)

RunChatCompletion runs a bounded model-and-tool loop on top of the plain CreateChatCompletion endpoint. When the model returns tool_calls, each call whose name matches a registered tool is executed locally and its result is fed back to the model; calls with no registered handler are returned to the model as an error observation so it can adjust. The loop stops when the model returns a message with no tool_calls or when MaxSteps is reached.

CreateChatCompletion delegates here only for SDK-owned defaults. Callers who supplied tools get primitive, non-executing behavior unless they explicitly invoke RunChatCompletion. If a later turn fails, the returned result is non-nil and retains every completed step and the accumulated transcript.

func (*Client) RunChatCompletionStream added in v0.1.1

func (c *Client) RunChatCompletionStream(ctx context.Context, request ChatCompletionRequest, opts RunChatStreamOptions) (*RunChatResult, error)

RunChatCompletionStream runs the same bounded model-and-tool loop as RunChatCompletion, but each model turn is consumed as a Server-Sent-Events stream so text can be surfaced token-by-token through RunChatStreamOptions.OnTextDelta. Tool calls accumulated during a stream are executed after that stream ends, their results are fed back, and the next turn opens a fresh stream. The loop stops when a streamed turn produces no tool calls or when MaxSteps is reached.

This is an additive entry point: StreamChatCompletion keeps its raw, non-executing streaming semantics unchanged, and the same registered tools drive it as the non-streaming loops. If a later turn fails, the returned result retains every completed step and the accumulated transcript.

func (*Client) RunMessage added in v0.1.1

func (c *Client) RunMessage(ctx context.Context, request MessageRequest, opts RunMessageOptions) (*RunMessageResult, error)

RunMessage executes Anthropic-compatible tool_use blocks until the model returns a final message or MaxSteps is reached. A request or local execution failure returns a non-nil partial result marked StoppedBy "error".

func (*Client) RunMessageStream added in v0.1.1

func (c *Client) RunMessageStream(ctx context.Context, request MessageRequest, opts RunMessageStreamOptions) (*RunMessageResult, error)

RunMessageStream runs a bounded Anthropic-compatible tool loop while each model turn is consumed as SSE. Text deltas and local tool results are exposed through callbacks, and the returned result contains the complete Messages transcript and per-turn responses.

func (*Client) RunResponse added in v0.1.1

func (c *Client) RunResponse(ctx context.Context, request ResponseRequest, opts RunResponseOptions) (*RunResponseResult, error)

RunResponse executes native Responses function calls until the model returns a final output or MaxSteps is reached. A request or local execution failure returns a non-nil partial result marked StoppedBy "error".

func (*Client) RunResponseStream added in v0.1.1

func (c *Client) RunResponseStream(ctx context.Context, request ResponseRequest, opts RunResponseStreamOptions) (*RunResponseResult, error)

RunResponseStream executes the Responses tool loop while consuming each model turn as native SSE. Failures retain a partial result marked "error".

func (*Client) StreamChatCompletion

func (c *Client) StreamChatCompletion(ctx context.Context, request ChatCompletionRequest) (*ChatCompletionStream, error)

StreamChatCompletion starts a streaming OpenAI-compatible completion. The caller must close the returned stream.

func (*Client) StreamMessage

func (c *Client) StreamMessage(ctx context.Context, request MessageRequest) (*MessageStream, error)

func (*Client) StreamResponse

func (c *Client) StreamResponse(ctx context.Context, request ResponseRequest) (*ResponseStream, error)

type ErrorCode added in v0.1.1

type ErrorCode string

ErrorCode is a provider-neutral classification of a failed request. It is aligned with the JoyToken TypeScript SDK so callers get identical error semantics across languages.

const (
	ErrorCodeRateLimited    ErrorCode = "rate_limited"
	ErrorCodeServerError    ErrorCode = "server_error"
	ErrorCodeTimeout        ErrorCode = "timeout"
	ErrorCodeNetwork        ErrorCode = "network"
	ErrorCodeInvalidRequest ErrorCode = "invalid_request"
	ErrorCodeAuthentication ErrorCode = "authentication"
	ErrorCodePermission     ErrorCode = "permission"
	ErrorCodeNotFound       ErrorCode = "not_found"
	ErrorCodeUnknown        ErrorCode = "unknown"
)

type FilePermissionFunc added in v0.1.1

type FilePermissionFunc func(ctx context.Context, request FilePermissionRequest) (allow bool, err error)

FilePermissionFunc lets the host approve or reject a default file_write call. Returning false blocks the write. The file_write tool is always declared to the model; this callback is what makes it runnable. With no callback configured, the declaration is still sent but every write is refused at execution time, so the model sees the capability yet nothing is written without host approval. Read/exploration tools remain always available.

type FilePermissionRequest added in v0.1.1

type FilePermissionRequest struct {
	ToolName string
	Input    any
	Root     string
	Step     int
}

FilePermissionRequest describes a pending file_write invocation presented to the host for approval. The SDK never renders UI; the host decides. Path is the model-supplied relative path and Root is the resolved absolute sandbox root, so the host can show the user exactly where a write would land.

type FinishReasonKind added in v0.1.1

type FinishReasonKind int

FinishReasonKind is the SDK's provider-neutral classification of a model turn's finish_reason. Different gateways and model vendors spell their terminal states differently (OpenAI: "stop"/"tool_calls"/"length"; Gemini: "STOP"/"MALFORMED_FUNCTION_CALL"/"MAX_TOKENS"; Anthropic: "end_turn"/"tool_use"/"max_tokens"). The tool loop should never branch on those raw strings directly; it normalizes them into this small enum so the loop's control flow stays vendor-agnostic and new providers only need a new mapping entry here.

const (
	// FinishUnknown is an unrecognized or empty finish_reason. Treated as a
	// normal stop by the loop but kept distinct for diagnostics.
	FinishUnknown FinishReasonKind = iota
	// FinishStop is a clean end of turn: the model produced its final answer.
	FinishStop
	// FinishToolCalls means the model asked to call one or more tools.
	FinishToolCalls
	// FinishLength means the turn was cut off by a token/length limit.
	FinishLength
	// FinishContentFilter means the turn was blocked by a safety filter.
	FinishContentFilter
	// FinishMalformedToolCall means the model attempted a tool call but emitted
	// an unparseable/invalid payload that the gateway rejected. This is the
	// Gemini-family "malformed_function_call" case: the response carries no
	// usable tool_calls even though the model was trying to call one. It is
	// transient and worth retrying with a corrective nudge.
	FinishMalformedToolCall
)

func (FinishReasonKind) String added in v0.1.1

func (k FinishReasonKind) String() string

String renders the kind for diagnostics and StoppedBy values.

type GeneratedImage

type GeneratedImage struct {
	URL           string `json:"url,omitempty"`
	B64JSON       string `json:"b64_json,omitempty"`
	RevisedPrompt string `json:"revised_prompt,omitempty"`
}

GeneratedImage contains one URL or base64-encoded generated image.

type HTTPClient

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPClient is the subset of http.Client used by Client.

type ImageEditRequest added in v0.2.1

type ImageEditRequest struct {
	Model  string `json:"model,omitempty"`
	Prompt string `json:"prompt"`
	// Image is the source image(s) to edit. Use a string for a single image or
	// a []string for multiple images. Each value is an http(s) URL or a base64
	// data URI (data:<mime>;base64,<data>).
	Image          any    `json:"image"`
	N              *int   `json:"n,omitempty"`
	Size           string `json:"size,omitempty"`
	User           string `json:"user,omitempty"`
	ResponseFormat string `json:"response_format,omitempty"`
}

ImageEditRequest is an OpenAI-compatible image edit request. Prompt and Image are required by the JoyToken gateway. Image accepts a single http(s) URL or base64 data URI (string), or multiple of them ([]string). Model, when set, must be ModelAuto; other fields are forwarded to the selected image provider.

type ImageGenerationRequest

type ImageGenerationRequest struct {
	Model             string `json:"model"`
	Prompt            string `json:"prompt"`
	N                 *int   `json:"n,omitempty"`
	Quality           string `json:"quality,omitempty"`
	ResponseFormat    string `json:"response_format,omitempty"`
	Size              string `json:"size,omitempty"`
	Style             string `json:"style,omitempty"`
	User              string `json:"user,omitempty"`
	Background        string `json:"background,omitempty"`
	Moderation        string `json:"moderation,omitempty"`
	OutputCompression *int   `json:"output_compression,omitempty"`
	OutputFormat      string `json:"output_format,omitempty"`
}

ImageGenerationRequest is an OpenAI-compatible image generation request. Model must be ModelAuto and Prompt is required by the JoyToken gateway; other fields are forwarded to the selected image provider.

type ImageGenerationResponse

type ImageGenerationResponse struct {
	Created  int64            `json:"created,omitempty"`
	Data     []GeneratedImage `json:"data"`
	Metadata map[string]any   `json:"metadata,omitempty"`
}

ImageGenerationResponse is an OpenAI-compatible image generation result. Metadata contains JoyToken routing and billing details when available.

func (*ImageGenerationResponse) RequestID added in v0.1.2

func (r *ImageGenerationResponse) RequestID() string

RequestID returns the Gateway request ID carried in image metadata.

type ListModelsOptions

type ListModelsOptions struct {
	// Locale selects zh or en. An empty value leaves the parameter unset, so
	// the API returns its default English descriptions.
	Locale ModelLocale
}

ListModelsOptions configures a public model catalog request.

type MessageContentBlock

type MessageContentBlock struct {
	Type      string         `json:"type"`
	Text      string         `json:"text,omitempty"`
	ID        string         `json:"id,omitempty"`
	Name      string         `json:"name,omitempty"`
	Input     map[string]any `json:"input,omitempty"`
	ToolUseID string         `json:"tool_use_id,omitempty"`
	Content   any            `json:"content,omitempty"`
	// ThoughtSignature preserves the opaque, provider-specific reasoning token
	// (notably Gemini's top-level thought_signature returned by the gateway's
	// Chat Completions endpoint) across the Anthropic Messages protocol
	// adaptation. It MUST be echoed back verbatim on the continuation turn or
	// the provider rejects the request with a 503, so we carry it on the
	// tool_use block rather than dropping it during (de)serialization.
	ThoughtSignature string `json:"thought_signature,omitempty"`
	// ExtraContent preserves opaque provider metadata while adapting tool_use.
	ExtraContent map[string]any `json:"extra_content,omitempty"`
}

MessageContentBlock is an Anthropic Messages-compatible content block.

type MessageParam

type MessageParam struct {
	Role    string `json:"role"`
	Content any    `json:"content"`
}

type MessageRequest

type MessageRequest struct {
	Model       string         `json:"model"`
	MaxTokens   int            `json:"max_tokens"`
	Messages    []MessageParam `json:"messages"`
	System      any            `json:"system,omitempty"`
	Stream      bool           `json:"stream,omitempty"`
	Temperature *float64       `json:"temperature,omitempty"`
	Tools       []MessageTool  `json:"tools,omitempty"`
	ToolChoice  any            `json:"tool_choice,omitempty"`
	Tier        string         `json:"tier,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
}

MessageRequest is an Anthropic Messages-compatible request translated to the gateway's Chat Completions endpoint.

type MessageResponse

type MessageResponse struct {
	ID           string                `json:"id"`
	Type         string                `json:"type"`
	Role         string                `json:"role"`
	Content      []MessageContentBlock `json:"content"`
	Model        string                `json:"model"`
	StopReason   *string               `json:"stop_reason,omitempty"`
	StopSequence *string               `json:"stop_sequence,omitempty"`
	Usage        MessageUsage          `json:"usage"`
	Metadata     map[string]any        `json:"metadata,omitempty"`
}

func (*MessageResponse) RequestID added in v0.1.2

func (r *MessageResponse) RequestID() string

RequestID returns the Gateway request ID preserved by the Messages adapter.

type MessageStream

type MessageStream struct {
	// contains filtered or unexported fields
}

MessageStream adapts Chat Completions SSE into Anthropic Messages events.

func (*MessageStream) Close

func (s *MessageStream) Close() error

func (*MessageStream) Recv

func (s *MessageStream) Recv() (*MessageStreamEvent, error)

type MessageStreamEvent

type MessageStreamEvent struct {
	Type         string               `json:"type"`
	Index        *int                 `json:"index,omitempty"`
	Message      *MessageResponse     `json:"message,omitempty"`
	ContentBlock *MessageContentBlock `json:"content_block,omitempty"`
	Delta        map[string]any       `json:"delta,omitempty"`
	Usage        *MessageUsage        `json:"usage,omitempty"`
	Error        map[string]any       `json:"error,omitempty"`
	Metadata     map[string]any       `json:"metadata,omitempty"`
}

func (*MessageStreamEvent) RequestID added in v0.1.2

func (e *MessageStreamEvent) RequestID() string

RequestID returns the Gateway request ID from event metadata or its message.

type MessageTool

type MessageTool struct {
	Name        string         `json:"name"`
	Description string         `json:"description,omitempty"`
	InputSchema map[string]any `json:"input_schema"`
}

type MessageToolChoice added in v0.1.1

type MessageToolChoice struct {
	Type string `json:"type"`
	Name string `json:"name,omitempty"`
}

MessageToolChoice is the Anthropic-compatible tool_choice shape. Type may be "auto", "any", "tool", or "none"; Name is used with Type "tool".

type MessageToolStep added in v0.1.1

type MessageToolStep struct {
	Index       int
	Response    *MessageResponse
	ToolResults []ToolCallResult
	Usage       *MessageUsage
}

type MessageUsage

type MessageUsage struct {
	InputTokens              int `json:"input_tokens,omitempty"`
	OutputTokens             int `json:"output_tokens,omitempty"`
	CacheCreationInputTokens int `json:"cache_creation_input_tokens,omitempty"`
	CacheReadInputTokens     int `json:"cache_read_input_tokens,omitempty"`
}

type ModelInfo

type ModelInfo struct {
	ModelID                      string   `json:"modelId,omitempty"`
	ModelKey                     string   `json:"modelKey,omitempty"`
	DisplayName                  string   `json:"displayName,omitempty"`
	Alias                        string   `json:"alias,omitempty"`
	Tier                         string   `json:"tier,omitempty"`
	Tags                         []string `json:"tags,omitempty"`
	Description                  string   `json:"description,omitempty"`
	CustomerInputMtok            float64  `json:"customerInputMtok,omitempty"`
	CustomerOutputMtok           float64  `json:"customerOutputMtok,omitempty"`
	CustomerCachereadMtok        float64  `json:"customerCachereadMtok,omitempty"`
	CustomerCachewriteMtok       float64  `json:"customerCachewriteMtok,omitempty"`
	CustomerImageInputMtok       string   `json:"customerImageInputMtok,omitempty"`
	CustomerImageOutputMtok      string   `json:"customerImageOutputMtok,omitempty"`
	CustomerImageCachedInputMtok string   `json:"customerImageCachedInputMtok,omitempty"`
	Provider                     string   `json:"provider,omitempty"`
	FeatureTags                  []string `json:"featureTags,omitempty"`
	ScenarioTags                 []string `json:"scenarioTags,omitempty"`
	MCIScore                     float64  `json:"mciScore,omitempty"`
}

ModelInfo is a model summary returned by ListModels.

type ModelListData

type ModelListData struct {
	Models []ModelInfo `json:"models"`
}

ModelListData is the data envelope returned by the model catalog.

type ModelListResponse

type ModelListResponse struct {
	Code    int           `json:"code,omitempty"`
	Message string        `json:"message,omitempty"`
	Object  string        `json:"object,omitempty"`
	Data    ModelListData `json:"data"`
}

ModelListResponse contains the models available to the caller.

type ModelLocale

type ModelLocale string

ModelLocale selects the language used for localized model descriptions.

const (
	// ModelLocaleZH requests Chinese model descriptions.
	ModelLocaleZH ModelLocale = "zh"
	// ModelLocaleEN requests English model descriptions.
	ModelLocaleEN ModelLocale = "en"
)

type ModelMetadata

type ModelMetadata struct {
	Tiers         []CatalogOption `json:"tiers"`
	SKUs          []CatalogOption `json:"skus"`
	FeatureTags   []CatalogOption `json:"featureTags"`
	IndustryPacks []CatalogOption `json:"industryPacks"`
	Providers     []CatalogOption `json:"providers"`
	UpdatedAt     string          `json:"updatedAt"`
}

ModelMetadata contains available model catalog filter values.

type ModelMetadataResponse

type ModelMetadataResponse struct {
	Code    int           `json:"code"`
	Data    ModelMetadata `json:"data"`
	Message string        `json:"message"`
}

ModelMetadataResponse wraps model catalog metadata.

type Option

type Option func(*Client)

Option configures a Client.

func WithAPIBaseURL

func WithAPIBaseURL(apiBaseURL string) Option

WithAPIBaseURL configures the common JoyToken base URL. Because the gateway has one model entry point, it also derives openAIBaseURL as <base>/openai/v1. A later WithOpenAIBaseURL call may override it explicitly.

func WithAPIKey

func WithAPIKey(apiKey string) Option

WithAPIKey configures the API key used for authenticated requests.

func WithAnthropicBaseURL

func WithAnthropicBaseURL(_ string) Option

WithAnthropicBaseURL is retained for source compatibility. Anthropic Messages is now a local adapter over the gateway's single Chat Completions endpoint, so there is no separate Anthropic URL to configure. Deprecated: configure WithOpenAIBaseURL or WithAPIBaseURL instead.

func WithAnthropicVersion

func WithAnthropicVersion(_ string) Option

WithAnthropicVersion is retained for source compatibility. No Anthropic HTTP request is emitted by this SDK adapter. Deprecated: the value is ignored.

func WithDefaultBuiltinTools added in v0.1.1

func WithDefaultBuiltinTools(enabled bool) Option

WithDefaultBuiltinTools controls whether zero-config hosted Responses tools are sent when the caller supplied no tools. It is disabled by default because hosted tools may carry separate provider availability and billing semantics. Currently web_search_preview is the only opt-in hosted default; file_search still requires caller-provided vector_store_ids. Explicit request tools are always forwarded unchanged.

func WithDefaultLocalTools added in v0.1.1

func WithDefaultLocalTools(enabled bool) Option

WithDefaultLocalTools controls the SDK fallback tool set used when the caller supplies no request-level or registered tools. It includes compute/read tools plus permission-gated file_write and shell. Pass false to disable it.

func WithFilePermission added in v0.1.1

func WithFilePermission(ask FilePermissionFunc) Option

WithFilePermission installs the approval callback for the default file_write tool. file_write is always declared to the model; this callback is what allows writes to actually happen. Read and exploration tools (file_search, list_dir, file_read) are side-effect free and always runnable. Every write is gated: with no callback configured, the write is refused at execution time, otherwise the host approves each write with the resolved absolute root in hand.

func WithFileWorkspace added in v0.1.1

func WithFileWorkspace(root string) Option

WithFileWorkspace overrides the sandbox root used by the default file tools. When unset, the root defaults to the current working directory (os.Getwd), matching the Codex/Claude "project workspace" model. Pass an explicit directory to widen or narrow the boundary the model may explore.

func WithHTTPClient

func WithHTTPClient(httpClient HTTPClient) Option

WithHTTPClient configures the HTTP transport used by the client.

func WithHeader

func WithHeader(key, value string) Option

WithHeader adds a header to every request. Later calls replace the same key.

func WithMaxRetries added in v0.1.1

func WithMaxRetries(maxRetries int) Option

WithMaxRetries configures how many times a transient request failure is retried before the error is returned. Transient failures are HTTP 429 and 5xx responses and low-level transport errors; 4xx responses (except 429) are never retried because they will not succeed on replay. Retries use bounded exponential backoff with jitter and honor a Retry-After response header when present. Model requests are not inherently idempotent, so retries are disabled by default and should be enabled only when the caller accepts that risk. A negative value is treated as zero.

func WithOpenAIBaseURL

func WithOpenAIBaseURL(openAIBaseURL string) Option

WithOpenAIBaseURL configures the OpenAI-compatible API base URL.

func WithShellPermission added in v0.1.1

func WithShellPermission(ask ShellPermissionFunc) Option

WithShellPermission installs the approval callback for the default shell tool. The shell tool is always declared to the model; this callback is what allows its commands to actually run. Because a shell command can do anything the host process can, every invocation is gated: with no callback configured, the command is refused at execution time. The resolved working directory is passed to the callback so the host can show the user exactly what would run and where.

func WithShellWorkspace added in v0.1.1

func WithShellWorkspace(dir string) Option

WithShellWorkspace overrides the directory the default shell tool runs commands in. When unset, it defaults to the current working directory (os.Getwd), matching the file tools' project-workspace model.

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout configures the maximum duration for a request, including reading a non-streaming response or consuming a streaming response. A non-positive duration disables the SDK timeout.

func WithToolHandler added in v0.1.1

func WithToolHandler(name, description string, parameters map[string]any, execute ToolExecuteFunc) Option

WithToolHandler registers a single named executable tool. It is a convenience wrapper over WithTools for the common case of attaching one handler.

func WithTools added in v0.1.1

func WithTools(tools ...Tool) Option

WithTools registers executable tools on the client. A non-empty registered set replaces the SDK defaults. Primitive Create/Stream methods only expose and forward these user-owned tools; explicit Run methods execute them. Later registrations with the same name replace earlier ones while preserving first-seen ordering.

func WithoutDefaultTools added in v0.1.1

func WithoutDefaultTools(names ...string) Option

WithoutDefaultTools excludes specific default tools by name, giving per-tool opt-out on top of the coarse WithDefaultLocalTools/WithDefaultBuiltinTools switches. Names match the tool's declared name for local tools (e.g. "shell", "file_write", "calculator") and the Type for gateway built-in tools (e.g. "web_search_preview"). Excluded tools are neither declared nor executed. It never affects tools the caller registered explicitly via WithTools/ WithToolHandler; those always win. Calling it multiple times accumulates.

type OrchestrationBilling added in v0.1.5

type OrchestrationBilling struct {
	InputTokens        int    `json:"input_tokens,omitempty"`
	OutputTokens       int    `json:"output_tokens,omitempty"`
	CachedInputTokens  int    `json:"cached_input_tokens,omitempty"`
	CachedOutputTokens int    `json:"cached_output_tokens,omitempty"`
	CreditsUsed        string `json:"credits_used,omitempty"`
}

OrchestrationBilling holds the per-sub-task token accounting reported in orchestration metadata. The Gateway reports credits_used as a decimal string.

type OrchestrationLatency added in v0.1.5

type OrchestrationLatency struct {
	RoutingMS int `json:"routing_ms,omitempty"`
}

OrchestrationLatency holds the nested latency breakdown the Gateway reports per metadata entry.

type OrchestrationTaskMeta added in v0.1.5

type OrchestrationTaskMeta struct {
	RequestID  string                `json:"request_id,omitempty"`
	Model      string                `json:"model,omitempty"`
	Tier       string                `json:"tier,omitempty"`
	Tag        []string              `json:"tag,omitempty"`
	TaskID     string                `json:"task_id,omitempty"`
	TaskSeq    int                   `json:"task_seq,omitempty"`
	TaskStatus string                `json:"task_status,omitempty"`
	Latency    *OrchestrationLatency `json:"latency,omitempty"`
	Billing    *OrchestrationBilling `json:"billing,omitempty"`

	// Extra retains any fields not modeled above so callers keep access to the
	// raw metadata object without a second parse.
	Extra map[string]any `json:"-"`
}

OrchestrationTaskMeta is one entry of the per-sub-task metadata array a completion carries. The Gateway sends metadata as an array even for a single turn, so this doubles as the shape of any real metadata entry. task_id/seq/ status are only present when multi-step orchestration is engaged. Any field not modeled here (billing_id, score, model_recommendation, task_score, ...) is retained in Extra.

type PlanEntry added in v0.1.5

type PlanEntry struct {
	Seq    int    `json:"seq"`
	TaskID string `json:"task_id"`
	Title  string `json:"title,omitempty"`
}

PlanEntry is one planned sub-task announced by the orchestrator.

type Pricing

type Pricing struct {
	Tiers          []PricingTier `json:"tiers"`
	SKUs           []PricingSKU  `json:"skus"`
	CurrentVersion string        `json:"currentVersion"`
	UpdatedAt      string        `json:"updatedAt"`
}

Pricing contains the current tier and SKU catalog.

type PricingResponse

type PricingResponse struct {
	Code    int     `json:"code"`
	Data    Pricing `json:"data"`
	Message string  `json:"message"`
}

PricingResponse wraps the current pricing catalog.

type PricingSKU

type PricingSKU struct {
	Code        string `json:"code"`
	Name        string `json:"name"`
	Description string `json:"description"`
}

PricingSKU describes an available pricing SKU.

type PricingTier

type PricingTier struct {
	Code          string `json:"code"`
	Name          string `json:"name"`
	Description   string `json:"description"`
	USDPerCredit  string `json:"usdPerCredit"`
	CreditsPerUSD string `json:"creditsPerUsd"`
	Unit          string `json:"unit"`
	RateVersion   string `json:"rateVersion"`
	SortOrder     int32  `json:"sortOrder"`
	UpdatedAt     string `json:"updatedAt"`
}

PricingTier describes a JoyToken credit conversion tier.

type Response

type Response struct {
	ID                string               `json:"id"`
	Object            string               `json:"object"`
	CreatedAt         int64                `json:"created_at,omitempty"`
	Status            string               `json:"status"`
	Model             string               `json:"model"`
	Output            []ResponseOutputItem `json:"output,omitempty"`
	Usage             *ResponseUsage       `json:"usage,omitempty"`
	Metadata          map[string]any       `json:"metadata,omitempty"`
	Error             map[string]any       `json:"error,omitempty"`
	IncompleteDetails map[string]any       `json:"incomplete_details,omitempty"`
}

func (*Response) OutputText

func (r *Response) OutputText() string

func (*Response) RequestID added in v0.1.2

func (r *Response) RequestID() string

RequestID returns the Gateway request ID carried in response metadata.

type ResponseInputContentPart

type ResponseInputContentPart struct {
	Type string `json:"type"`
	Text string `json:"text"`
}

ResponseInputContentPart is one text part in a Responses input message.

type ResponseInputItem

type ResponseInputItem struct {
	Type             string `json:"type,omitempty"`
	ID               string `json:"id,omitempty"`
	Role             string `json:"role,omitempty"`
	Status           string `json:"status,omitempty"`
	Content          any    `json:"content,omitempty"`
	CallID           string `json:"call_id,omitempty"`
	Name             string `json:"name,omitempty"`
	Arguments        string `json:"arguments,omitempty"`
	Output           string `json:"output,omitempty"`
	Summary          []any  `json:"summary,omitempty"`
	EncryptedContent string `json:"encrypted_content,omitempty"`
	// ExtraContent preserves opaque provider metadata across Responses turns.
	ExtraContent map[string]any `json:"extra_content,omitempty"`
}

ResponseInputItem is one OpenAI Responses-compatible input item. It covers message input plus the function_call/function_call_output items used by the SDK's native Responses tool loop.

type ResponseOutputContent

type ResponseOutputContent struct {
	Type        string `json:"type"`
	Text        string `json:"text,omitempty"`
	Annotations []any  `json:"annotations,omitempty"`
}

type ResponseOutputItem

type ResponseOutputItem struct {
	ID               string                  `json:"id,omitempty"`
	Type             string                  `json:"type"`
	Role             string                  `json:"role,omitempty"`
	Status           string                  `json:"status,omitempty"`
	Content          []ResponseOutputContent `json:"content,omitempty"`
	CallID           string                  `json:"call_id,omitempty"`
	Name             string                  `json:"name,omitempty"`
	Arguments        string                  `json:"arguments,omitempty"`
	Summary          []any                   `json:"summary,omitempty"`
	EncryptedContent string                  `json:"encrypted_content,omitempty"`
	// ExtraContent preserves opaque provider metadata across Responses turns.
	ExtraContent map[string]any `json:"extra_content,omitempty"`
	Action       map[string]any `json:"action,omitempty"`
	Results      []any          `json:"results,omitempty"`
}

type ResponseRequest

type ResponseRequest struct {
	Model              string         `json:"model"`
	Input              any            `json:"input"`
	Instructions       string         `json:"instructions,omitempty"`
	Stream             bool           `json:"stream,omitempty"`
	MaxOutputTokens    *int           `json:"max_output_tokens,omitempty"`
	Temperature        *float64       `json:"temperature,omitempty"`
	TopP               *float64       `json:"top_p,omitempty"`
	Tools              []ResponseTool `json:"tools"`
	ToolChoice         any            `json:"tool_choice,omitempty"`
	ParallelToolCalls  *bool          `json:"parallel_tool_calls,omitempty"`
	PreviousResponseID string         `json:"previous_response_id,omitempty"`
	Include            []string       `json:"include,omitempty"`
	Store              *bool          `json:"store,omitempty"`
	Tier               string         `json:"tier,omitempty"`
	Metadata           map[string]any `json:"metadata,omitempty"`
}

ResponseRequest is an OpenAI Responses-compatible request sent directly to /openai/v1/responses. Model must be ModelAuto.

type ResponseStream

type ResponseStream struct {
	// contains filtered or unexported fields
}

ResponseStream reads native Responses SSE events from the gateway.

func (*ResponseStream) Close

func (s *ResponseStream) Close() error

func (*ResponseStream) Recv

type ResponseStreamEvent

type ResponseStreamEvent struct {
	Type           string                 `json:"type"`
	SequenceNumber int                    `json:"sequence_number"`
	Response       *Response              `json:"response,omitempty"`
	OutputIndex    int                    `json:"output_index,omitempty"`
	ContentIndex   int                    `json:"content_index,omitempty"`
	ItemID         string                 `json:"item_id,omitempty"`
	Item           *ResponseOutputItem    `json:"item,omitempty"`
	Part           *ResponseOutputContent `json:"part,omitempty"`
	Delta          string                 `json:"delta,omitempty"`
	Text           string                 `json:"text,omitempty"`
	Arguments      string                 `json:"arguments,omitempty"`
	Error          map[string]any         `json:"error,omitempty"`
}

func (*ResponseStreamEvent) RequestID added in v0.1.2

func (e *ResponseStreamEvent) RequestID() string

RequestID returns the Gateway request ID from this event's response envelope.

type ResponseTool

type ResponseTool struct {
	Type string `json:"type"`

	Name        string         `json:"name,omitempty"`
	Description string         `json:"description,omitempty"`
	Parameters  map[string]any `json:"parameters,omitempty"`
	Strict      *bool          `json:"strict,omitempty"`

	SearchContextSize string                      `json:"search_context_size,omitempty"`
	UserLocation      *ResponseToolUserLocation   `json:"user_location,omitempty"`
	VectorStoreIDs    []string                    `json:"vector_store_ids,omitempty"`
	MaxNumResults     *int                        `json:"max_num_results,omitempty"`
	Filters           map[string]any              `json:"filters,omitempty"`
	RankingOptions    *ResponseToolRankingOptions `json:"ranking_options,omitempty"`
}

ResponseTool declares either a function tool or a vendor-hosted Responses tool. Declarations are sent directly to the gateway's Responses endpoint.

type ResponseToolRankingOptions added in v0.1.1

type ResponseToolRankingOptions struct {
	Ranker         string   `json:"ranker,omitempty"`
	ScoreThreshold *float64 `json:"score_threshold,omitempty"`
}

type ResponseToolStep added in v0.1.1

type ResponseToolStep struct {
	Index       int
	Response    *Response
	ToolResults []ToolCallResult
	Usage       *ResponseUsage
}

type ResponseToolUserLocation added in v0.1.1

type ResponseToolUserLocation struct {
	Type     string `json:"type,omitempty"`
	Country  string `json:"country,omitempty"`
	City     string `json:"city,omitempty"`
	Region   string `json:"region,omitempty"`
	Timezone string `json:"timezone,omitempty"`
}

type ResponseUsage

type ResponseUsage struct {
	InputTokens  int `json:"input_tokens,omitempty"`
	OutputTokens int `json:"output_tokens,omitempty"`
	TotalTokens  int `json:"total_tokens,omitempty"`
}

type RunChatOptions added in v0.1.1

type RunChatOptions struct {
	// MaxSteps bounds how many model/tool round-trips the loop runs. Zero uses
	// defaultToolMaxSteps.
	MaxSteps int
}

RunChatOptions configures one RunChatCompletion execution loop. It is an additive, opt-in surface: it does not change ChatCompletionRequest or any existing method, so callers that never touch RunChatCompletion are unaffected.

type RunChatResult added in v0.1.1

type RunChatResult struct {
	FinalText string
	Messages  []ChatMessage
	Steps     []ToolStep
	// StoppedBy is "stop" for a final answer, "max_steps" when the configured
	// bound is exhausted, or "error" when a request or local execution fails.
	StoppedBy string
	// FinishReason is the normalized, provider-neutral classification of why
	// the loop stopped. It is "error" when a request or local execution fails.
	// "malformed_function_call" here
	// means the loop exhausted its retries on a model that kept emitting
	// invalid tool-call payloads, so the caller can distinguish a real answer
	// from a vendor-side tool-calling failure instead of seeing an empty
	// FinalText with StoppedBy "stop".
	FinishReason string
}

RunChatResult is the final state of a RunChatCompletion loop.

type RunChatStreamOptions added in v0.1.1

type RunChatStreamOptions struct {
	// MaxSteps bounds how many model/tool round-trips the loop runs. Zero uses
	// defaultToolMaxSteps.
	MaxSteps int

	// OnTextDelta, when set, receives each incremental assistant text chunk as
	// it streams in, across every step of the loop. It lets callers render
	// tokens live while the loop still handles tool execution automatically.
	OnTextDelta func(delta string)

	// OnToolResult, when set, is called after each tool call is executed with
	// its result, so callers can surface tool activity mid-stream.
	OnToolResult func(result ToolCallResult)

	// OnOrchestration, when set, receives each Gateway orchestration event as
	// it streams in: the planning phase (with the full plan) and each sub-task
	// status transition. It is never called for a non-orchestrated stream.
	OnOrchestration func(event *ChunkOrchestration)

	// OnPlan, when set, is called once with the orchestrator's plan the first
	// time it arrives, as a convenience over filtering OnOrchestration.
	OnPlan func(plan []PlanEntry)
}

RunChatStreamOptions configures one RunChatCompletionStream execution loop. It is additive and opt-in: it does not change StreamChatCompletion or any existing method.

type RunMessageOptions added in v0.1.1

type RunMessageOptions struct {
	// MaxSteps bounds model/tool round-trips. Zero uses the SDK default.
	MaxSteps int
}

type RunMessageResult added in v0.1.1

type RunMessageResult struct {
	FinalText string
	Messages  []MessageParam
	Steps     []MessageToolStep
	// StoppedBy is "stop", "max_steps", or "error". On error, Steps and
	// Messages retain all work completed before the failure.
	StoppedBy string
}

type RunMessageStreamOptions added in v0.1.1

type RunMessageStreamOptions struct {
	// MaxSteps bounds model/tool round-trips. Zero uses the SDK default.
	MaxSteps int
	// OnTextDelta receives each Messages-compatible text increment.
	OnTextDelta func(delta string)
	// OnToolResult runs after each local tool execution.
	OnToolResult func(result ToolCallResult)
}

RunMessageStreamOptions configures an Anthropic-compatible streaming tool loop. It mirrors the Chat and Responses streaming run options while keeping the wire request on the gateway's single Chat Completions endpoint.

type RunResponseOptions added in v0.1.1

type RunResponseOptions struct {
	// MaxSteps bounds model/tool round-trips. Zero uses the SDK default.
	MaxSteps int
}

type RunResponseResult added in v0.1.1

type RunResponseResult struct {
	FinalText string
	Input     []ResponseInputItem
	Steps     []ResponseToolStep
	// StoppedBy is "stop", "max_steps", or "error". On error, Steps and Input
	// retain all work completed before the failure.
	StoppedBy string
}

type RunResponseStreamOptions added in v0.1.1

type RunResponseStreamOptions struct {
	MaxSteps     int
	OnTextDelta  func(delta string)
	OnToolResult func(result ToolCallResult)
}

type ShellPermissionFunc added in v0.1.1

type ShellPermissionFunc func(ctx context.Context, request ShellPermissionRequest) (allow bool, err error)

ShellPermissionFunc lets the host approve or reject a default shell call. Returning false blocks the command. The shell tool is always declared to the model; this callback is what makes it runnable. With no callback configured, the declaration is still sent but every invocation is refused at execution time, so the model sees the capability yet nothing runs without host approval.

type ShellPermissionRequest added in v0.1.1

type ShellPermissionRequest struct {
	ToolName   string
	Input      any
	Command    string
	WorkingDir string
	Step       int
}

ShellPermissionRequest describes a pending shell invocation presented to the host for approval. The SDK never renders UI; the host decides. Command is the model-supplied command line and WorkingDir is the resolved directory it would run in, so the host can show the user exactly what would execute and where.

type Tool added in v0.1.1

type Tool = tooldef.Tool

Tool describes a function the model can call.

func DefineTool added in v0.1.1

func DefineTool(t Tool) Tool

DefineTool returns tool unchanged and documents the intended construction point for code that shares tool definitions across packages.

type ToolCall

type ToolCall = tooldef.ToolCall

ToolCall describes a model-requested function call.

type ToolCallResult added in v0.1.1

type ToolCallResult struct {
	ToolCallID string
	ToolName   string
	Content    string
	IsError    bool
}

ToolCallResult records the serialized result of one tool call. IsError is true when the tool failed (bad arguments, a runtime error, or a panic) and Content carries the error message fed back to the model so it can retry.

type ToolExecuteFunc added in v0.1.1

type ToolExecuteFunc = tooldef.ToolExecuteFunc

ToolExecuteFunc is the signature of a tool's execution function.

type ToolExecutionContext added in v0.1.1

type ToolExecutionContext = tooldef.ToolExecutionContext

ToolExecutionContext contains the state available to a tool invocation.

type ToolFunction

type ToolFunction = tooldef.ToolFunction

ToolFunction identifies a function and its JSON arguments.

type ToolStep added in v0.1.1

type ToolStep struct {
	Index            int
	AssistantMessage ChatMessage
	ToolResults      []ToolCallResult
	Usage            *Usage

	// FinishReason is the raw provider finish_reason for this turn, kept for
	// diagnostics. The loop branches on the normalized FinishReasonKind, not
	// this string.
	FinishReason string
	// contains filtered or unexported fields
}

ToolStep records one model response and the tool results produced from it.

type Usage

type Usage struct {
	PromptTokens     int      `json:"prompt_tokens,omitempty"`
	CompletionTokens int      `json:"completion_tokens,omitempty"`
	TotalTokens      int      `json:"total_tokens,omitempty"`
	Cost             *float64 `json:"cost,omitempty"`
	TotalCost        *float64 `json:"total_cost,omitempty"`
}

Usage reports token and cost information for a request.

Directories

Path Synopsis
Package agent provides tool-calling agent helpers built on the JoyToken client.
Package agent provides tool-calling agent helpers built on the JoyToken client.
toolkit
Package toolkit provides a built-in tool set for agents, following a convention-over-configuration model: when a host application does not supply its own tools, the agent can inject a safe default set (compute-class, zero-cost, local tools).
Package toolkit provides a built-in tool set for agents, following a convention-over-configuration model: when a host application does not supply its own tools, the agent can inject a safe default set (compute-class, zero-cost, local tools).
Package tool re-exports the shared tool abstraction for code that composes tools (toolkits, MCP/Skill adapters) without pulling in the whole client surface.
Package tool re-exports the shared tool abstraction for code that composes tools (toolkits, MCP/Skill adapters) without pulling in the whole client surface.
Package tooldef holds the tool-related wire types and the sharedTool abstraction at the very bottom of the JoyToken dependency graph.
Package tooldef holds the tool-related wire types and the sharedTool abstraction at the very bottom of the JoyToken dependency graph.

Jump to

Keyboard shortcuts

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