Files
Agent-Native/runtime/llm/types.go
T
agent-exec-transport 899fd70d27
ci / docker-checkout-hostgateway (pull_request) Successful in 12s
governance / governance (pull_request) Successful in 35s
ci / vet-and-test (pull_request) Successful in 1m24s
agent-exec transport e38bcf1cbe415c5d6a3e91773d811b0a/445c377b4484
2026-10-20 04:03:18 +00:00

197 lines
7.9 KiB
Go

package llm
import (
"context"
"encoding/json"
"time"
)
// Role is a transcript role carried into the provider request.
type Role string
const (
RoleSystem Role = "system"
RoleUser Role = "user"
RoleAssistant Role = "assistant"
RoleTool Role = "tool"
)
// StopReason is the terminal condition of one assistant turn.
type StopReason string
const (
StopEnd StopReason = "end"
StopToolCalls StopReason = "toolCalls"
StopError StopReason = "error"
StopAborted StopReason = "aborted"
)
// EventKind identifies one item on the assistant stream.
type EventKind string
const (
KindTextDelta EventKind = "text_delta"
KindReasoningDelta EventKind = "reasoning_delta"
KindToolCallDelta EventKind = "tool_call_delta"
KindMessageEnd EventKind = "message_end"
KindError EventKind = "error"
)
// ToolCall is one function call requested by the assistant.
type ToolCall struct {
ID string `json:"id"`
Name string `json:"name"`
Arguments string `json:"arguments"`
}
// Message is one transcript entry. System, user, assistant, and tool results share this shape.
type Message struct {
Role Role `json:"role"`
Content string `json:"content,omitempty"`
Name string `json:"name,omitempty"`
Images []Image `json:"images,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
// Thinking 是思考块:Anthropic 原生路径含签名、在请求里原样往返;
// OpenAI 兼容路径由 SSE 的 reasoning_content 捕获(不含签名),随会话
// 转录持久化,请求序列化时按 <think> 块回放(见 client.go replayThink)。
Thinking []ThinkingBlock `json:"thinking,omitempty"`
StopReason StopReason `json:"stop_reason,omitempty"`
IsError bool `json:"is_error,omitempty"`
}
// ThinkingBlock 是一块 Anthropic 思考内容。Redacted 为真时 Data 是不透明
// 密文(redacted_thinking),往返时原样回送。
type ThinkingBlock struct {
Thinking string `json:"thinking,omitempty"`
Signature string `json:"signature,omitempty"`
Redacted bool `json:"redacted,omitempty"`
Data string `json:"data,omitempty"`
}
// ToolDecl is the JSON-schema declaration sent to the provider.
type ToolDecl struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters json.RawMessage `json:"parameters"`
}
// Image is one picture attached to a user message.
type Image struct {
MIME string `json:"mime,omitempty"`
URL string `json:"url,omitempty"`
Data string `json:"data,omitempty"`
}
// Usage counts tokens. On one provider response, PromptTokens, CompletionTokens
// and TotalTokens are that request. On a loop Result they are the billing sum
// across requests; Last* is only the latest request, for context observation.
// Zero means the provider omitted usage.
type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
CacheReadTokens int `json:"cache_read_tokens,omitempty"`
CacheWriteTokens int `json:"cache_write_tokens,omitempty"`
LastPromptTokens int `json:"last_prompt_tokens,omitempty"`
LastCompletionTokens int `json:"last_completion_tokens,omitempty"`
LastTotalTokens int `json:"last_total_tokens,omitempty"`
}
// TerminalObservation records how a stream ended without retaining provider
// content, tool identity, arguments, request headers, or error text. Counts
// saturate at fixed limits; this evidence never authorizes a tool call.
type TerminalObservation struct {
ReadOutcome string `json:"readOutcome"`
LastFrameJSONComplete bool `json:"lastFrameJSONComplete"`
UsagePresent bool `json:"usagePresent"`
ToolFragments int `json:"toolFragments"`
ToolArgumentBytes int `json:"toolArgumentBytes"`
ToolArgumentsValid bool `json:"toolArgumentsValid"`
// TailEventKind is the structural class of the last SSE event the parser
// completed: done_literal, json_frame, empty_data, comment,
// unknown_non_json, partial_frame or unknown. TailEventCount counts those
// events and saturates at 10000. Neither marks the stream complete.
TailEventKind string `json:"tailEventKind"`
TailEventCount int `json:"tailEventCount"`
// BodyBoundary is set only by Client on a response it received; a bare
// ParseSSE call leaves it nil.
BodyBoundary *BodyBoundaryObservation `json:"bodyBoundary,omitempty"`
// CompletionBasis mirrors Event.CompletionBasis.
CompletionBasis string `json:"completionBasis,omitempty"`
// ContractCheck is the first route-contract condition, C1 through C9, that
// failed when a configured RouteContractEOF did not release a stream that
// ended without [DONE]. Empty when no contract evaluated the stream.
ContractCheck string `json:"contractCheck,omitempty"`
}
// BodyBoundaryObservation records how the client read one HTTP response body.
// It holds only fixed enums, booleans and a saturated byte count. Reaching
// EOF proves only that the body ended, not that the SSE stream completed.
type BodyBoundaryObservation struct {
// ProtocolClass is http1, http2 or other.
ProtocolClass string `json:"protocolClass"`
// FramingClass is known_length, chunked, http2_stream, close_delimited or unknown.
FramingClass string `json:"framingClass"`
DeclaredLengthKnown bool `json:"declaredLengthKnown"`
BytesRead int64 `json:"bytesRead"`
BytesSaturated bool `json:"bytesSaturated"`
EOFSeen bool `json:"eofSeen"`
// LengthRelation is match, mismatch or unknown.
LengthRelation string `json:"lengthRelation"`
Uncompressed bool `json:"uncompressed"`
}
// Event is one streamed update. Failures are KindError plus a final assistant
// message whose StopReason is error or aborted. Stream implementations do not panic.
type Event struct {
Kind EventKind
Text string
ReasoningDelta string
ToolIndex int
ToolID string
ToolName string
ArgumentsDelta string
Message Message
Usage Usage
// FinishReason 是供应商原始结束原因(stop、length、tool_calls 等)。
// 空表示这条事件不携带结束原因。StopReason 的映射不受此字段影响。
FinishReason string
// StreamComplete records whether the OpenAI-compatible SSE stream supplied
// its explicit [DONE] marker. Tool calls require this before execution
// unless CompletionBasis is route_contract_eof.
StreamComplete bool
// CompletionBasis is set by Client on a successful OpenAI-chat message_end:
// done_marker when [DONE] arrived, route_contract_eof when RouteContractEOF
// released tool calls without it. Empty otherwise.
CompletionBasis string
// TerminalObservation is present only on a terminal/error event. It does
// not change StreamComplete or the tool-execution safety gate.
TerminalObservation *TerminalObservation
Err error
Retryable bool
ErrorMessage string
// HTTPStatus 是提供方的 HTTP 状态;0 表示尚无 HTTP 响应。
HTTPStatus int
// RetryAfter is the provider's requested wait. HasRetryAfter distinguishes
// a real zero from a missing or unparseable header.
RetryAfter time.Duration
HasRetryAfter bool
}
// StreamOptions tunes one provider request.
type StreamOptions struct {
MaxTokens int
APIBase string
APIKey string
// ThinkingLevel is off, minimal, low, medium, high, xhigh, or max.
// Empty leaves the provider default unchanged.
ThinkingLevel string
// MessageShape is merge, strict, or empty. Empty leaves the transcript unchanged.
MessageShape string
}
// StreamFunc is the provider boundary. It must return a channel that is closed
// after a terminal message_end or error event. It must not panic.
type StreamFunc func(ctx context.Context, model string, messages []Message, tools []ToolDecl, opts StreamOptions) <-chan Event