Documentation
¶
Overview ¶
Package llm provides a unified abstraction layer for Large Language Model interactions within the Mattermost AI plugin.
This package defines the core interfaces and data structures for working with various LLM providers (OpenAI, Anthropic, etc.) in a consistent manner. It handles:
- LanguageModel interface abstraction for different LLM providers
- Conversation management with structured posts, roles, and context
- Prompt template system with embedded templates and variable substitution
- Streaming text responses for real-time chat interactions
- Tool/function calling capabilities with JSON schema validation
- Request/response structures with token counting and truncation
- Context management including user info, channels, and bot configurations
The package is designed to be provider-agnostic, allowing the plugin to work with multiple LLM services through a common interface while preserving provider-specific capabilities like vision, JSON output, and tool calling.
Index ¶
- Constants
- Variables
- func BareMCPToolName(toolName string) string
- func BatchSkippedToolResult(toolName string, unavailableNames []string) string
- func CloneHTTPClientWithTransport(client *http.Client, transport http.RoundTripper) *http.Client
- func CountTrailingFailedToolCalls(posts []Post) int
- func CreateTokenLogger() (*mlog.Logger, error)
- func EnrichToolCall(tc *ToolCall, store *ToolStore, opts EnrichToolCallOptions)
- func EscapePromptContent(s string) string
- func EstimateRequestTokens(inputs []CompositionInput) int
- func EstimateTokens(text string) int
- func GenerateBenchText(size int) string
- func IsBareMCPToolName(name string) bool
- func IsBatchSkippedToolResult(result string) bool
- func IsResolvedToolCallBatch(toolCalls []ToolCall) bool
- func IsSupportedImageMimeType(mimeType string) bool
- func IsToolRetryExempt(name string) bool
- func IsValidService(service ServiceConfig) bool
- func MCPToolNameMatches(runtimeName, configuredName string) bool
- func NamespaceMCPToolName(serverSlug, bareToolName string) string
- func NewJSONSchemaFromStruct[T any]() *jsonschema.Schema
- func NormalizeMCPServerOrigin(origin string) string
- func NormalizeMCPServerOrigins(origins []string) []string
- func SanitizeNonPrintableChars(s string) string
- func SanitizeProviderError(err error, configuredAPIKeys ...string) error
- func SanitizeProviderErrorMessage(message string, configuredAPIKeys ...string) string
- func ServiceUsesResponsesAPI(cfg ServiceConfig) bool
- func StripMarkdownCodeFencing(s string) string
- func UTF16CodeUnitCount(s string) int
- type Annotation
- type AnnotationType
- type BenchmarkScenario
- type BotConfig
- type ChannelAccessLevel
- type CompletionRequest
- type Composition
- type CompositionComponent
- type CompositionInput
- type CompositionSource
- type Context
- func (c *Context) AddCreatedFile(f CreatedFile)
- func (c *Context) AddSandboxFiles(refs ...ProviderFileReference)
- func (c *Context) ConsumeSandboxFiles() []ProviderFileReference
- func (c *Context) CreatedFilesList() []CreatedFile
- func (c *Context) CustomPromptVars() map[string]string
- func (c *Context) MarkMCPDynamicToolLoaded(name string)
- func (c *Context) MarkMCPDynamicToolSearch()
- func (c *Context) ObserveMCPDynamicToolEvent(event, result string)
- func (c *Context) ResponseAttachmentSlots() int
- func (c *Context) SetBotFields(...)
- func (c *Context) SetResponseAttachmentBudget(remaining int)
- func (c *Context) ShouldRecordMCPDynamicSearchLoadCallSuccess(name string) bool
- func (c Context) String() string
- type ContextOption
- type CreatedFile
- type CustomAuthTransport
- type EnabledMCPTool
- type EnrichToolCallOptions
- type EventType
- type File
- type LanguageModel
- type LanguageModelConfig
- type LanguageModelOption
- func WithJSONOutput[T any]() LanguageModelOption
- func WithMaxGeneratedTokens(maxGeneratedTokens int) LanguageModelOption
- func WithModel(model string) LanguageModelOption
- func WithNativeWebSearchAllowed() LanguageModelOption
- func WithReasoningDisabled() LanguageModelOption
- func WithToolsDisabled() LanguageModelOption
- type LanguageModelTestLogWrapper
- func (w *LanguageModelTestLogWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
- func (w *LanguageModelTestLogWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
- func (w *LanguageModelTestLogWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
- func (w *LanguageModelTestLogWrapper) InputTokenLimit() int
- func (w *LanguageModelTestLogWrapper) OutputTokenLimit() int
- type LanguageModelWrapper
- type MCPDynamicToolTelemetry
- type MetricsObserver
- type ModelInfo
- type OpenAICompatibleProvider
- type Post
- type PostRole
- type Prompts
- type ProviderFile
- type ProviderFileDownloader
- type ProviderFileReference
- type ProviderServices
- type ReasoningData
- type SanitizedProviderError
- type ServerToolUse
- type ServiceConfig
- type StreamGenerator
- type StructuredOutputFallbackWrapper
- func (w *StructuredOutputFallbackWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
- func (w *StructuredOutputFallbackWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
- func (w *StructuredOutputFallbackWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
- func (w *StructuredOutputFallbackWrapper) InputTokenLimit() int
- func (w *StructuredOutputFallbackWrapper) OutputTokenLimit() int
- type TextRange
- type TextStreamEvent
- type TextStreamResult
- type TokenUsage
- type TokenUsageLoggingWrapper
- func (w *TokenUsageLoggingWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
- func (w *TokenUsageLoggingWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
- func (w *TokenUsageLoggingWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
- func (w *TokenUsageLoggingWrapper) InputTokenLimit() int
- func (w *TokenUsageLoggingWrapper) OutputTokenLimit() int
- type TokenUsagePluginLogger
- type TokenUsageSinks
- func (s *TokenUsageSinks) FileLogger() *mlog.Logger
- func (s *TokenUsageSinks) LoggingEnabled() bool
- func (s *TokenUsageSinks) PluginLogger() TokenUsagePluginLogger
- func (s *TokenUsageSinks) SetFileEnabled(enabled bool)
- func (s *TokenUsageSinks) SetFileLogger(logger *mlog.Logger)
- func (s *TokenUsageSinks) SetLoggingEnabled(enabled bool)
- func (s *TokenUsageSinks) SetPluginEnabled(enabled bool)
- type Tool
- type ToolArgumentGetter
- type ToolAuthError
- type ToolCall
- type ToolCallStatus
- type ToolCatalogContext
- type ToolInfo
- type ToolLookup
- type ToolResolver
- type ToolRuntimeContext
- func (t *ToolRuntimeContext) AddCreatedFile(f CreatedFile)
- func (t *ToolRuntimeContext) AddSandboxFiles(refs ...ProviderFileReference)
- func (t *ToolRuntimeContext) CreatedFilesList() []CreatedFile
- func (t *ToolRuntimeContext) MarkMCPDynamicToolLoaded(name string)
- func (t *ToolRuntimeContext) MarkMCPDynamicToolSearch()
- func (t *ToolRuntimeContext) ObserveMCPDynamicToolEvent(botName, event, result string)
- func (t *ToolRuntimeContext) ResponseAttachmentSlots() int
- func (t *ToolRuntimeContext) SetResponseAttachmentBudget(remaining int)
- func (t *ToolRuntimeContext) ShouldRecordMCPDynamicSearchLoadCallSuccess(name string) bool
- type ToolStore
- func (s *ToolStore) AddAuthError(authError ToolAuthError)
- func (s *ToolStore) AddTools(tools []Tool)
- func (s *ToolStore) GetAuthErrors() []ToolAuthError
- func (s *ToolStore) GetServerOrigin(toolName string) string
- func (s *ToolStore) GetTool(name string) *Tool
- func (s *ToolStore) GetTools() []Tool
- func (s *ToolStore) GetToolsInfo() []ToolInfo
- func (s *ToolStore) GetUnloadedMCPToolInfo(name string) (ToolInfo, bool)
- func (s *ToolStore) HasUnloadedMCPTools() bool
- func (s *ToolStore) IsUnloadedMCPTool(name string) bool
- func (s *ToolStore) KeepToolsIf(keep func(Tool) bool)
- func (s *ToolStore) LoadMCPTools(names []string) []Tool
- func (s *ToolStore) LookupTool(name, serverOrigin string) (ToolLookup, bool)
- func (s *ToolStore) RemoveToolsByServerOrigin(disabledOrigins []string)
- func (s *ToolStore) ResolveTool(ctx context.Context, name string, argsGetter ToolArgumentGetter, ...) (string, error)
- func (s *ToolStore) RetainOnlyMCPTools(allowlist []EnabledMCPTool)
- func (s *ToolStore) SetUnloadedMCPTools(tools []Tool)
- type TruncationWrapper
- func (w *TruncationWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
- func (w *TruncationWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
- func (w *TruncationWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
- func (w *TruncationWrapper) InputTokenLimit() int
- func (w *TruncationWrapper) OutputTokenLimit() int
- type TurnSegment
- type TurnSequence
- func (s *TurnSequence) AppendReasoning(text string)
- func (s *TurnSequence) AppendText(text string)
- func (s *TurnSequence) FinishReasoning(data ReasoningData)
- func (s *TurnSequence) HasText() bool
- func (s *TurnSequence) RecordServerTools(uses []ServerToolUse)
- func (s *TurnSequence) RemoveTextRanges(original string, ranges []TextRange) bool
- func (s *TurnSequence) Reset()
- func (s *TurnSequence) Segments() []TurnSegment
- func (s *TurnSequence) Text() string
- type UserAccessLevel
Constants ¶
const ( // CompositionTotalCounted means the total came from a provider // CountTokens call (most accurate, pre-call). CompositionTotalCounted = "counted" // CompositionTotalProvider means the total came from the provider's // post-call usage report (most accurate, post-call). CompositionTotalProvider = "provider" // CompositionTotalEstimated means we fell back to EstimateTokens because // neither a counter nor a provider report was available. CompositionTotalEstimated = "estimated" )
CompositionTotalSource enumerates the provenance of Composition.Total.
const ( ServiceTypeOpenAI = "openai" ServiceTypeOpenAICompatible = "openaicompatible" ServiceTypeAzure = "azure" ServiceTypeAnthropic = "anthropic" ServiceTypeCohere = "cohere" ServiceTypeBedrock = "bedrock" ServiceTypeMistral = "mistral" ServiceTypeScale = "scale" ServiceTypeGemini = "gemini" ServiceTypeVertex = "vertex" ServiceTypeLoadTestMock = "loadtest_mock" )
const ( // NativeToolWebSearch is provider web search (OpenAI web_search, Anthropic // web_search, Gemini/Vertex Google Search grounding). NativeToolWebSearch = "web_search" // NativeToolWebFetch is Anthropic's web_fetch server tool: retrieve the full // content of specific web pages / PDFs. NativeToolWebFetch = "web_fetch" // NativeToolFileSearch is OpenAI's file_search tool over vector stores. // Reserved: not currently offered or sent — OpenAI requires // vector_store_ids on the tool definition and the plugin has no // vector-store configuration surface yet (see // bifrost.SupportedNativeToolsForServiceType). NativeToolFileSearch = "file_search" // NativeToolCodeInterpreter is the provider code sandbox: OpenAI's // code_interpreter, or Anthropic's code_execution tool. For Anthropic this // also opts web_search/web_fetch into sandbox-based dynamic filtering (see // bifrost.convertToResponsesTools). NativeToolCodeInterpreter = "code_interpreter" )
Native (provider-executed) tool ids stored in BotConfig.EnabledNativeTools. The same ids are used by the webapp's native-tools checklist. Which ids each service type supports is defined by bifrost.SupportedNativeToolsForServiceType.
const ( ServerToolStatusInProgress = "in_progress" ServerToolStatusSuccess = "success" ServerToolStatusError = "error" )
Server tool activity status values. They intentionally match the conversation content-block status strings so the streaming layer can persist them verbatim.
const ( // TokenUsageLogEvent is the canonical event name for structured token usage logs. // #nosec G101 -- this is a non-secret log event identifier. TokenUsageLogEvent = "llm_token_usage" // TokenUsageLogSchemaVersion is the version of the token usage log field // contract. Bump only on breaking changes; new optional fields don't count. TokenUsageLogSchemaVersion = 1 // TokenUsageUnknown is the normalized value for missing dimensions. TokenUsageUnknown = "unknown" )
const ( OperationConversation = "conversation" OperationConversationToolFollowup = "conversation_tool_followup" OperationTitleGeneration = "title_generation" OperationChannelSummary = "channel_summary" OperationChannelInterval = "channel_interval" OperationThreadAnalysis = "thread_analysis" OperationSearch = "search" OperationMeetingSummary = "meeting_summary" OperationMeetingChunkSummary = "meeting_chunk_summary" OperationEmojiSelection = "emoji_selection" OperationWebSearchSummarization = "web_search_summarization" OperationEvalGrading = "eval_grading" OperationBridgeAgent = "bridge_agent" OperationBridgeService = "bridge_service" )
operation identifies the high-level feature or action producing token usage.
const ( ToolAuthModeUser = "user" ToolAuthModeServiceAccount = "service_account" )
tool_auth_mode identifies which auth mode the request's tool catalog was built with.
const ( SubTypeStreaming = "streaming" SubTypeNoStream = "nostream" SubTypeToolCall = "tool_call" SubTypeTranscriptionChunk = "transcription_chunk" SubTypeChunkedTrue = "chunked_true" SubTypeChunkedFalse = "chunked_false" )
operation_subtype is a low-cardinality detail for the operation. Typical values represent modality or a small scenario class (for example streaming vs non-streaming, tool calls, or chunk modes).
const ( TurnSegmentText = "text" TurnSegmentThinking = "thinking" TurnSegmentServerTool = "server_tool" )
const DefaultMaxToolTurns = 30
DefaultMaxToolTurns is the default tool-call-execute-recall ceiling per LLM turn. Agents that store 0 (legacy config bots, freshly-migrated rows before the column was added) fall back to this value via BotConfig.EffectiveMaxToolTurns.
const FunctionsTokenBudget = 200
const MCPServerToolWildcard = "*"
MCPServerToolWildcard in EnabledMCPTool.ToolName means every tool from that ServerOrigin is allowed.
const MCPToolNameSeparator = "__"
const MaxAllowedMaxToolTurns = 250
MaxAllowedMaxToolTurns caps user-provided MaxToolTurns to keep runaway loops bounded even if a misconfigured agent requests an unreasonably high value.
const MaxConsecutiveToolCallFailures = 3
const MaxCustomInstructionsRunes = 100000
MaxCustomInstructionsRunes bounds the per-turn LLM system prompt and agent-save request. Custom instructions are sent only to the LLM, not as Mattermost posts.
const MaxPostAttachments = 10
MaxPostAttachments is the Mattermost per-post attachment limit. It bounds how many files tools may create for or attach to a single post.
const MinTokens = 100
const PlaceholderAPIKey = "custom-auth"
PlaceholderAPIKey is a sentinel value for SDKs that require a non-empty API key when real authentication is handled by the transport (e.g., custom auth headers).
const PromptExtension = "tmpl"
const SafetyCheckThreshold = 0.8
SafetyCheckThreshold gates the provider-side count call. We only ask for an exact count when the heuristic estimate is at or above this fraction of the truncation budget.
const TokenLimitBufferSize = 0.9
const ToolIterationLimitUserMessage = "" /* 233-byte string literal not displayed */
const ToolRetryLimitSystemMessage = "" /* 142-byte string literal not displayed */
const UserInteractionSelect = "select"
UserInteractionSelect identifies tools answered by the user picking from a set of options presented in the Mattermost UI.
Variables ¶
var ErrUnsupportedTokenCount = errors.New("token counting not supported by this provider")
ErrUnsupportedTokenCount signals that the underlying provider does not support exact input-token counting. Callers should fall back to EstimateTokens when they see this error.
Functions ¶
func BareMCPToolName ¶
func BatchSkippedToolResult ¶
BatchSkippedToolResult marks a tool result as skipped because another tool in the same batch was unavailable. The message is still surfaced to the LLM and UI as an error, but it must not count toward MaxConsecutiveToolCallFailures.
func CloneHTTPClientWithTransport ¶
CloneHTTPClientWithTransport creates a shallow copy of the given http.Client with the specified transport, preserving Timeout, CheckRedirect, and Jar. If client is nil, a new http.Client with only the transport is returned.
func CountTrailingFailedToolCalls ¶
CountTrailingFailedToolCalls counts consecutive trailing tool executions that failed. A successful tool execution resets the streak. Posts without executed tool results stop the scan because they represent a new agent turn.
func CreateTokenLogger ¶
CreateTokenLogger creates a dedicated logger for token usage metrics
func EnrichToolCall ¶
func EnrichToolCall(tc *ToolCall, store *ToolStore, opts EnrichToolCallOptions)
EnrichToolCall fills a tool call's Description, Title, ServerOrigin, and MCPBareName from the resolved store entry. MCPBareName is only set for MCP tools (those with a server origin); builtins are left untouched. Title and Description follow the same overwrite semantics: rehydration trusts the store (OverwriteDescription), approval preserves any value already present.
func EscapePromptContent ¶
EscapePromptContent replaces angle brackets in user-generated content to prevent injection of fake XML structural elements into prompt templates.
func EstimateRequestTokens ¶
func EstimateRequestTokens(inputs []CompositionInput) int
EstimateRequestTokens is the fallback total used when no provider counter is available. It mirrors the same weighting as ComputeComposition, so an image-heavy request still contributes via imageWeightPlaceholder rather than silently rounding to zero (image CompositionInputs carry no Text).
func EstimateTokens ¶
EstimateTokens is a fast, synchronous, provider-agnostic approximation. For an exact count, call LanguageModel.CountTokens instead.
func GenerateBenchText ¶
GenerateBenchText creates a string of the specified size using a repeating pattern. Uses a realistic text pattern rather than random bytes.
func IsBareMCPToolName ¶
IsBareMCPToolName reports whether name is non-empty and has no MCP server namespace prefix (e.g. "get_issue" rather than "jira__get_issue").
func IsResolvedToolCallBatch ¶ added in v2.7.0
IsResolvedToolCallBatch reports whether a ToolCalls event represents the post-execution "resolved" broadcast (every call has a terminal status assigned by toolrunner after execution) rather than the pre-execution "pending" broadcast. toolrunner.buildResolvedToolCalls tags successful auto-run tools as AutoApproved (not Success) and errored ones as Error; user-approved tools are later tagged Success by the approval flow. Anything else — most commonly Pending, but also Rejected — indicates the batch has not been executed. Streaming persistence and the annotation decorator both reset per-round state at this boundary, so they must share this predicate.
func IsToolRetryExempt ¶
IsToolRetryExempt identifies MCP dynamic-loading meta-tools. Keep these names in sync with mcp.SearchToolsName and mcp.LoadToolName without importing mcp here, which would create a package cycle.
func IsValidService ¶
func IsValidService(service ServiceConfig) bool
IsValidService validates a service configuration
func MCPToolNameMatches ¶
func NamespaceMCPToolName ¶
func NewJSONSchemaFromStruct ¶
func NewJSONSchemaFromStruct[T any]() *jsonschema.Schema
NewJSONSchemaFromStruct creates a JSONSchema from a Go struct using generics It's a helper function for tool providers that currently define schemas as structs
func NormalizeMCPServerOrigin ¶
NormalizeMCPServerOrigin trims formatting variants used around MCP server origins.
func NormalizeMCPServerOrigins ¶
NormalizeMCPServerOrigins returns unique, non-empty normalized MCP origins.
func SanitizeNonPrintableChars ¶
SanitizeNonPrintableChars replaces non-printable Unicode characters with their escaped representation [U+XXXX] to prevent text spoofing attacks such as bidirectional text attacks that can make URLs appear to point to different domains. Uses [U+XXXX] format instead of \uXXXX to avoid JSON parsers converting it back. Allows newline, tab, and carriage return for JSON formatting. Also escapes variation selectors and other default ignorable code points which are technically "printable" but render invisibly and can be used for spoofing.
func SanitizeProviderError ¶
SanitizeProviderError redacts API keys, bearer tokens, and similar material from provider errors before those strings are logged, streamed to clients, or returned to callers.
func SanitizeProviderErrorMessage ¶
SanitizeProviderErrorMessage applies the same redaction rules as SanitizeProviderError to a plain string. Each configured API key is additionally redacted when it appears as a substring (word-boundary safe). Pass the primary key plus any fallback keys so a fallback provider's credential in a custom key format (e.g. Gemini, Mistral, or a local OpenAI-compatible key) is redacted even when the generic patterns miss it.
func ServiceUsesResponsesAPI ¶
func ServiceUsesResponsesAPI(cfg ServiceConfig) bool
ServiceUsesResponsesAPI reports whether the Responses API path is used for this service. Direct OpenAI always uses it; OpenAI-compatible and Azure honor the operator toggle. All other service types ignore UseResponsesAPI — a stale flag carried over from a previous service type must not be allowed to route the request through Responses.
func StripMarkdownCodeFencing ¶
StripMarkdownCodeFencing removes markdown code block fencing (e.g. ```json ... ```) that LLMs sometimes wrap around JSON responses despite being instructed not to.
func UTF16CodeUnitCount ¶
UTF16CodeUnitCount returns the length of a string in JavaScript-compatible UTF-16 code units. The frontend applies annotation indices with JS string slicing, so locally computed offsets must use this unit.
Types ¶
type Annotation ¶
type Annotation struct {
Type AnnotationType `json:"type"` // Type of annotation
StartIndex int `json:"start_index"` // Start position in message text (0-based, JS UTF-16 code units)
EndIndex int `json:"end_index"` // End position in message text (0-based, JS UTF-16 code units)
URL string `json:"url,omitempty"` // Source URL (for url_citation)
Title string `json:"title,omitempty"` // Source title (for url_citation)
CitedText string `json:"cited_text,omitempty"` // Optional: text being cited (for context)
Index int `json:"index"` // Display index (1-based for UI)
}
Annotation represents an inline annotation/citation in the response text. Indices are stored in JavaScript UTF-16 code units so they can be applied directly by the webapp's string slicing.
type AnnotationType ¶
type AnnotationType string
AnnotationType represents different types of annotations
const ( // AnnotationTypeURLCitation represents a web search citation AnnotationTypeURLCitation AnnotationType = "url_citation" )
type BenchmarkScenario ¶
type BenchmarkScenario struct {
Name string
Generator StreamGenerator
}
BenchmarkScenario defines a benchmark test scenario
func BenchmarkScenarios ¶
func BenchmarkScenarios() []BenchmarkScenario
BenchmarkScenarios returns common scenarios for stream benchmarks. This combines size-based scenarios with event-type scenarios.
type BotConfig ¶
type BotConfig struct {
ID string `json:"id"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
CustomInstructions string `json:"customInstructions"`
ServiceID string `json:"serviceID"`
// Model is the optional model override for this bot.
// If not specified, the service's DefaultModel will be used.
Model string `json:"model"`
// Service is deprecated and kept only for backwards compatibility during migration.
Service *ServiceConfig `json:"service,omitempty"`
EnableVision bool `json:"enableVision"`
DisableTools bool `json:"disableTools"`
ChannelAccessLevel ChannelAccessLevel `json:"channelAccessLevel"`
ChannelIDs []string `json:"channelIDs"`
UserAccessLevel UserAccessLevel `json:"userAccessLevel"`
UserIDs []string `json:"userIDs"`
TeamIDs []string `json:"teamIDs"`
MaxFileSize int64 `json:"maxFileSize"`
// EnabledNativeTools contains the list of enabled native tools for this bot
// (see the NativeTool* constants). Which ids a provider actually supports is
// defined by bifrost.SupportedNativeToolsForServiceType; unsupported values
// are filtered out at request time. For OpenAI-compatible and Azure services,
// native tools additionally require UseResponsesAPI.
EnabledNativeTools []string `json:"enabledNativeTools"`
// EnabledMCPTools is the per-agent allowlist of MCP tools:
// only tools matching these (ServerOrigin, ToolName) pairs are kept.
// Ignored when AutoEnableNewMCPTools is true.
EnabledMCPTools []EnabledMCPTool `json:"enabledMCPTools"`
// AutoEnableNewMCPTools, when true, gives this agent access to every currently
// configured MCP tool and any MCP tool added later. EnabledMCPTools is ignored
// in that mode. When false, only tools listed in EnabledMCPTools are available.
AutoEnableNewMCPTools bool `json:"autoEnableNewMCPTools"`
// MCPDynamicToolLoading controls whether this bot uses the JIT MCP tool loading flow.
// It defaults to true for omitted legacy config.
MCPDynamicToolLoading bool `json:"mcpDynamicToolLoading"`
// UseServiceAccountAuth switches external MCP access for this agent to
// admin-configured ServiceAccountHeaders instead of per-user OAuth.
// Embedded Mattermost and plugin MCP servers still run as the requesting user.
UseServiceAccountAuth bool `json:"useServiceAccountAuth"`
// ReasoningEnabled determines whether reasoning/thinking is enabled for this bot.
// Applicable to OpenAI (with ResponsesAPI), Anthropic, and Gemini / Vertex AI.
ReasoningEnabled bool `json:"reasoningEnabled"`
// ReasoningEffort determines the reasoning effort level.
// Valid values: "minimal", "low", "medium", "high".
// Applicable to OpenAI (with ResponsesAPI) and Gemini / Vertex AI (maps to
// Gemini's thinkingLevel on 3.0+, and to a thinkingBudget estimate on 2.5).
// Default: "medium".
ReasoningEffort string `json:"reasoningEffort"`
// ThinkingBudget determines the token budget for reasoning/thinking.
// - Anthropic: must be at least 1024 and cannot exceed the OutputTokenLimit.
// Default: 1/4 of OutputTokenLimit, capped at 8192.
// - Gemini / Vertex AI: maps to thinkingConfig.thinkingBudget. When set, it
// takes priority over ReasoningEffort.
ThinkingBudget int `json:"thinkingBudget"`
// StructuredOutputEnabled controls how a requested JSONOutputFormat schema is handled.
// When enabled, the schema is sent natively to the provider to constrain the model's
// output. When disabled, the schema is converted into prompt instructions and stripped
// from the provider request, for models/APIs without native structured output support.
StructuredOutputEnabled bool `json:"structuredOutputEnabled"`
// MaxToolTurns is the maximum number of LLM-call → tool-execute iterations
// the tool runner will perform for this agent before stopping. A non-positive
// value falls back to DefaultMaxToolTurns. Lower this when using a smaller
// model that tends to call tools in loops; raise it for agents that rely on
// long dynamic-tool-discovery chains (e.g. search → load → execute).
MaxToolTurns int `json:"maxToolTurns"`
// Admin / lifecycle metadata.
BotUserID string `json:"botUserID,omitempty"`
CreatorID string `json:"creatorID,omitempty"`
AdminUserIDs []string `json:"adminUserIDs,omitempty"`
CreateAt int64 `json:"createAt,omitempty"`
UpdateAt int64 `json:"updateAt,omitempty"`
DeleteAt int64 `json:"deleteAt,omitempty"`
}
func (BotConfig) EffectiveMaxToolTurns ¶
EffectiveMaxToolTurns returns the configured MaxToolTurns or DefaultMaxToolTurns when the value is non-positive (e.g. legacy config bots that never set the field).
func (*BotConfig) IsAdmin ¶
IsAdmin reports whether userID is the agent's creator or in the admin list. Returns false for the empty userID to avoid matching legacy bots (CreatorID == "").
func (*BotConfig) IsCreator ¶
IsCreator reports whether userID is the agent's creator. Returns false for migrated/config bots whose CreatorID is empty.
func (*BotConfig) IsValid ¶
IsValid reports whether the bot config is valid. Prefer Validate when a descriptive error is useful.
func (*BotConfig) UnmarshalJSON ¶
type ChannelAccessLevel ¶
type ChannelAccessLevel int
const ( ChannelAccessLevelAll ChannelAccessLevel = iota ChannelAccessLevelAllow ChannelAccessLevelBlock ChannelAccessLevelNone )
type CompletionRequest ¶
type CompletionRequest struct {
Posts []Post
Context *Context
Operation string
OperationSubType string
}
func (CompletionRequest) Composition ¶
func (r CompletionRequest) Composition() []CompositionInput
Composition derives the per-source attribution for this request from its posts and tool context. It is a pure function of the request, so it stays consistent through truncation and needs no stored state.
func (CompletionRequest) ExtractSystemMessage ¶
func (b CompletionRequest) ExtractSystemMessage() string
ExtractSystemMessage extracts the system message from the conversation.
func (CompletionRequest) String ¶
func (b CompletionRequest) String() string
type Composition ¶
type Composition struct {
Components []CompositionComponent `json:"components"`
Total int `json:"total"`
TotalSource string `json:"total_source"`
InputTokenLimit int `json:"input_token_limit,omitempty"`
Model string `json:"model,omitempty"`
}
Composition is the per-request, per-source token breakdown that powers the /context endpoint and the LLM-call span attributes.
func ComputeComposition ¶
func ComputeComposition(inputs []CompositionInput, total int, totalSource string) Composition
ComputeComposition returns the per-source breakdown for a set of inputs, scaled to the given total. Only the ratios from the cheap estimator are exposed — the published total always matches `total`. One row per source, emitted in compositionOrder.
func (Composition) SpanAttributes ¶
func (c Composition) SpanAttributes() []attribute.KeyValue
SpanAttributes returns OTel attribute key/value pairs for the per-source token totals, one per category. Zero-token buckets are omitted to keep trace cardinality bounded.
type CompositionComponent ¶
type CompositionComponent struct {
Source CompositionSource `json:"source"`
Proportion float64 `json:"proportion"`
Tokens int `json:"tokens"`
}
CompositionComponent is a single per-source row in a composition breakdown. Proportion is normalized so Components sum to 1.0 (modulo rounding); Tokens is round(Proportion * Total).
type CompositionInput ¶
type CompositionInput struct {
Source CompositionSource
Text string
}
CompositionInput is a single piece of content captured for attribution.
type CompositionSource ¶
type CompositionSource string
CompositionSource labels where a piece of an LLM request came from. Used to attribute token cost back to its origin (system prompt, history, tool definitions, tool results, images) without changing how a request is assembled or billed. Attachment text is part of the message, so it counts as history.
const ( SourceSystem CompositionSource = "system" SourceHistory CompositionSource = "history" SourceToolDefs CompositionSource = "tool_defs" SourceToolResults CompositionSource = "tool_results" SourceImage CompositionSource = "image" )
type Context ¶
type Context struct {
// Server
Time string
ServerName string
CompanyName string
SiteURL string
// Location
Team *model.Team
Channel *model.Channel
Thread []Post // Normalized posts that already have been formatted. nil if not in a thread or a root post
// User that is making the request
RequestingUser *model.User
// Bot Specific
BotName string
BotUsername string
BotUserID string
BotModel string
BotServiceType string
CustomInstructions string
// ToolAuthMode records the identity mode the tool catalog was built with
// (ToolAuthModeUser or ToolAuthModeServiceAccount); consumed by token usage attribution.
ToolAuthMode string
Tools *ToolStore
DisabledToolsInfo []ToolInfo // Info about tools that are unavailable in the current context (e.g., DM-only tools in a channel)
Parameters map[string]interface{}
// ToolCatalog holds request-scoped inputs used while building the tool store.
ToolCatalog ToolCatalogContext
// ToolRuntime holds non-prompt tool execution state for this turn.
ToolRuntime ToolRuntimeContext
}
Context represents the per-turn data necessary to build the context of the LLM. For consumers none of the fields can be assumed to be present.
func NewContext ¶
func NewContext(opts ...ContextOption) *Context
NewContext creates a new Context with the given options
func (*Context) AddCreatedFile ¶ added in v2.6.0
func (c *Context) AddCreatedFile(f CreatedFile)
AddCreatedFile records a file created by a tool during this turn so it can be attached to the response post. Files with an empty ID are skipped.
func (*Context) AddSandboxFiles ¶ added in v2.7.0
func (c *Context) AddSandboxFiles(refs ...ProviderFileReference)
AddSandboxFiles records observed sandbox files in arrival order. Empty references and repeated route/id pairs are skipped because snapshots are cumulative.
func (*Context) ConsumeSandboxFiles ¶ added in v2.7.0
func (c *Context) ConsumeSandboxFiles() []ProviderFileReference
ConsumeSandboxFiles returns observed files and clears them so a stream that ends twice cannot attach the same provider file again.
func (*Context) CreatedFilesList ¶ added in v2.6.0
func (c *Context) CreatedFilesList() []CreatedFile
CreatedFilesList returns the files created by tools during this turn.
func (*Context) CustomPromptVars ¶
CustomPromptVars returns a flat map of whitelisted variables for use in user-created custom prompt templates. Only safe, useful fields are exposed.
func (*Context) MarkMCPDynamicToolLoaded ¶
func (*Context) MarkMCPDynamicToolSearch ¶
func (c *Context) MarkMCPDynamicToolSearch()
func (*Context) ObserveMCPDynamicToolEvent ¶
func (*Context) ResponseAttachmentSlots ¶ added in v2.6.0
ResponseAttachmentSlots returns how many more files response tools may create this turn: the recorded budget, or the full MaxPostAttachments budget when none was set.
func (*Context) SetBotFields ¶
func (c *Context) SetBotFields(displayName, username, userID, defaultModel, serviceType, customInstructions string)
SetBotFields populates bot-related context fields from config and service values. This avoids duplicating bot field assignment across multiple packages.
func (*Context) SetResponseAttachmentBudget ¶ added in v2.6.0
SetResponseAttachmentBudget records how many more files the response post can hold, so file-creating tools reject excess calls before uploading.
func (*Context) ShouldRecordMCPDynamicSearchLoadCallSuccess ¶
type ContextOption ¶
type ContextOption func(*Context)
ContextOption defines a function that configures a Context
type CreatedFile ¶ added in v2.6.0
CreatedFile identifies a file created by a tool during this turn for attachment to the response post.
type CustomAuthTransport ¶
type CustomAuthTransport struct {
// Base is the underlying RoundTripper. If nil, http.DefaultTransport is used.
Base http.RoundTripper
// RemoveHeaders is a list of header names to remove from the request.
RemoveHeaders []string
// SetHeaders is a map of header names to values to set on the request.
SetHeaders map[string]string
}
CustomAuthTransport is an http.RoundTripper that removes and sets headers on outgoing requests. It clones requests to avoid mutating the original.
type EnabledMCPTool ¶
type EnabledMCPTool struct {
ServerOrigin string `json:"server_origin"`
ToolName string `json:"tool_name"`
}
EnabledMCPTool identifies a single MCP tool on a specific server (config bots and persisted agents).
type EnrichToolCallOptions ¶
type EnrichToolCallOptions struct {
// OverwriteDescription replaces an existing Description with the store's
// value. Rehydration trusts the store; approval preserves the model's text.
OverwriteDescription bool
// BareNameFallback retries the lookup by MCPBareName when the primary
// (name, origin) lookup misses (needed when rehydrating persisted blocks).
BareNameFallback bool
}
EnrichToolCallOptions controls how EnrichToolCall fills a tool call from the store.
type EventType ¶
type EventType int
EventType represents the type of event in the text stream
const ( // EventTypeText represents a text chunk event EventTypeText EventType = iota // EventTypeEnd represents the end of the stream EventTypeEnd // EventTypeError represents an error event EventTypeError // EventTypeToolCalls represents a tool call event EventTypeToolCalls // EventTypeReasoning represents a reasoning summary chunk event EventTypeReasoning // EventTypeReasoningEnd represents the end of reasoning summary EventTypeReasoningEnd // EventTypeAnnotations represents annotations/citations in the response EventTypeAnnotations // EventTypeUsage represents token usage data EventTypeUsage // EventTypeFiles carries the IDs of files created during the turn that // should be attached to the response post. Value is []string of // Mattermost file IDs. EventTypeFiles // EventTypeServerToolUse represents provider-executed (server) tool // activity — e.g. Anthropic web_search / web_fetch / code_execution or // OpenAI web_search / code_interpreter. The value is the cumulative // []ServerToolUse for the current round; receivers replace prior state. EventTypeServerToolUse )
type LanguageModel ¶
type LanguageModel interface {
ChatCompletion(ctx context.Context, conversation CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
ChatCompletionNoStream(ctx context.Context, conversation CompletionRequest, opts ...LanguageModelOption) (string, error)
// CountTokens returns the exact input-token count. Implementations that
// can't reach a provider counting endpoint return ErrUnsupportedTokenCount
// so callers can fall back to EstimateTokens.
CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
InputTokenLimit() int
OutputTokenLimit() int
}
type LanguageModelConfig ¶
type LanguageModelOption ¶
type LanguageModelOption func(*LanguageModelConfig)
func WithJSONOutput ¶
func WithJSONOutput[T any]() LanguageModelOption
func WithMaxGeneratedTokens ¶
func WithMaxGeneratedTokens(maxGeneratedTokens int) LanguageModelOption
func WithModel ¶
func WithModel(model string) LanguageModelOption
func WithNativeWebSearchAllowed ¶
func WithNativeWebSearchAllowed() LanguageModelOption
func WithReasoningDisabled ¶
func WithReasoningDisabled() LanguageModelOption
func WithToolsDisabled ¶
func WithToolsDisabled() LanguageModelOption
type LanguageModelTestLogWrapper ¶
type LanguageModelTestLogWrapper struct {
// contains filtered or unexported fields
}
func NewLanguageModelTestLogWrapper ¶
func NewLanguageModelTestLogWrapper(t *testing.T, wrapped LanguageModel) *LanguageModelTestLogWrapper
func (*LanguageModelTestLogWrapper) ChatCompletion ¶
func (w *LanguageModelTestLogWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
func (*LanguageModelTestLogWrapper) ChatCompletionNoStream ¶
func (w *LanguageModelTestLogWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
func (*LanguageModelTestLogWrapper) CountTokens ¶
func (w *LanguageModelTestLogWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
func (*LanguageModelTestLogWrapper) InputTokenLimit ¶
func (w *LanguageModelTestLogWrapper) InputTokenLimit() int
func (*LanguageModelTestLogWrapper) OutputTokenLimit ¶
func (w *LanguageModelTestLogWrapper) OutputTokenLimit() int
type LanguageModelWrapper ¶
type LanguageModelWrapper func(LanguageModel) LanguageModel
type MCPDynamicToolTelemetry ¶
type MCPDynamicToolTelemetry interface {
ObserveMCPDynamicToolEvent(botName, event, result string)
}
type MetricsObserver ¶
type MetricsObserver interface {
ObserveTokenUsage(botName, teamID, userID string, inputTokens, outputTokens int)
}
MetricsObserver defines the interface for observing token usage metrics
type ModelInfo ¶
type ModelInfo struct {
ID string `json:"id"`
DisplayName string `json:"displayName"`
InputTokenLimit *int `json:"inputTokenLimit,omitempty"`
OutputTokenLimit *int `json:"outputTokenLimit,omitempty"`
ContextLength *int `json:"contextLength,omitempty"`
}
ModelInfo represents information about an available model. The pointer limit fields are nil when the provider doesn't report them.
type OpenAICompatibleProvider ¶
type OpenAICompatibleProvider struct {
// DefaultModel used when none is configured.
DefaultModel string
// CreateTransport returns a custom RoundTripper for non-standard auth.
// If nil, the default HTTP client is used (standard Bearer token auth).
CreateTransport func(cfg ServiceConfig, base http.RoundTripper) http.RoundTripper
// DisableStreamOptions disables the stream_options parameter.
DisableStreamOptions bool
// UseMaxTokens uses max_tokens instead of max_completion_tokens.
UseMaxTokens bool
}
OpenAICompatibleProvider describes the configuration for an OpenAI-compatible provider that can be registered in the provider registry. Adding an entry to the registry is all that is needed to support a new provider — no changes to bots.go or api.go are required.
func GetOpenAICompatibleProvider ¶
func GetOpenAICompatibleProvider(serviceType string) (OpenAICompatibleProvider, bool)
GetOpenAICompatibleProvider returns the provider configuration for the given service type, if it is registered.
type Post ¶
type Post struct {
Role PostRole
Message string
Files []File
ToolUse []ToolCall
Reasoning string // Extended thinking/reasoning content from models that support it
ReasoningSignature string // Signature for thinking blocks (opaque verification field)
// ServerTools is provider-executed activity from this turn. The provider
// drops those results from later requests, so we replay a labeled summary
// (not reconstructed blocks: fields are truncated and the sandbox is gone).
ServerTools []ServerToolUse
// AssistantSegments is arrival order of text vs server-tool activity.
// ServerTools holds payloads; segments reference them by ID.
AssistantSegments []TurnSegment
}
type Prompts ¶
type Prompts struct {
// contains filtered or unexported fields
}
type ProviderFile ¶ added in v2.7.0
type ProviderFile struct {
// Name is model-influenced for sandbox output; sanitize before use.
Name string
ContentType string
Content []byte
}
ProviderFile is a provider-side file's content and metadata.
type ProviderFileDownloader ¶ added in v2.7.0
type ProviderFileDownloader interface {
DownloadProviderFile(ctx context.Context, ref ProviderFileReference, maxBytes int64) (ProviderFile, error)
}
ProviderFileDownloader serves provider-side files. Reach it through ProviderServices.FileDownloader, never by asserting on LanguageModel. A positive maxBytes rejects a file whose provider-reported metadata size exceeds it before any content is fetched; 0 disables the gate.
type ProviderFileReference ¶ added in v2.7.0
ProviderFileReference identifies a provider-side file. ProviderRoute is opaque: preserve it exactly and never expose it to users.
type ProviderServices ¶ added in v2.7.0
type ProviderServices struct {
FileDownloader ProviderFileDownloader
}
ProviderServices is resolved from the concrete provider client before it is wrapped. Do not recover these capabilities by type-asserting LanguageModel: the bot's model is a decorator chain, so the assertion silently fails.
Add a field per capability, left nil when the provider cannot perform it.
func (*ProviderServices) CanDownloadFiles ¶ added in v2.7.0
func (s *ProviderServices) CanDownloadFiles() bool
CanDownloadFiles is false for a nil receiver (unresolved services or mocks).
type ReasoningData ¶
type ReasoningData struct {
Text string // The reasoning/thinking text content
Signature string // Opaque verification signature from the model
}
ReasoningData represents the complete reasoning/thinking data including signature
type SanitizedProviderError ¶
type SanitizedProviderError struct {
// contains filtered or unexported fields
}
SanitizedProviderError wraps an upstream LLM error after redacting secrets from its message. It implements errors.Unwrap so errors.Is / errors.As chains on the original error are preserved.
func (*SanitizedProviderError) Error ¶
func (e *SanitizedProviderError) Error() string
func (*SanitizedProviderError) Unwrap ¶
func (e *SanitizedProviderError) Unwrap() error
type ServerToolUse ¶ added in v2.6.0
type ServerToolUse struct {
ID string `json:"id"`
Tool string `json:"tool"`
Status string `json:"status"`
// Query is the web_search query.
Query string `json:"query,omitempty"`
// URL is the web_fetch target (request URL, replaced by the resolved
// result URL when the fetch completes).
URL string `json:"url,omitempty"`
// Title is the fetched document title (web_fetch).
Title string `json:"title,omitempty"`
// SubTool is the code-execution sub-tool: "bash", "text_editor" or
// "python" (Anthropic), empty for providers without sub-tools.
SubTool string `json:"sub_tool,omitempty"`
// Command is the code or shell command executed in the sandbox.
Command string `json:"command,omitempty"`
// Output is the execution output (stdout/logs, with stderr appended when
// present) or other human-readable result summary.
Output string `json:"output,omitempty"`
// ErrorCode is the provider error code when the invocation failed.
ErrorCode string `json:"error_code,omitempty"`
// FileIDs are provider-side ids of files left in the sandbox output directory.
FileIDs []string `json:"file_ids,omitempty"`
// ProviderRoute is the Bifrost route that produced FileIDs. Runtime-only:
// needed for fallback downloads, never broadcast or persisted for display.
ProviderRoute string `json:"-"`
}
ServerToolUse describes one provider-executed tool invocation observed on the stream. Tool uses the same neutral ids as BotConfig.EnabledNativeTools (NativeToolWebSearch, NativeToolWebFetch, NativeToolCodeInterpreter); the remaining fields are populated per tool and pre-truncated for display.
func CloneServerToolUses ¶ added in v2.7.0
func CloneServerToolUses(uses []ServerToolUse) []ServerToolUse
CloneServerToolUses copies FileIDs so presentation sanitation cannot mutate the canonical provider replay snapshot.
func (ServerToolUse) Clone ¶ added in v2.7.0
func (s ServerToolUse) Clone() ServerToolUse
Clone returns a copy whose FileIDs slice is independent of the original, so presentation-side mutation cannot corrupt the canonical replay snapshot.
func (*ServerToolUse) Sanitize ¶ added in v2.6.0
func (s *ServerToolUse) Sanitize()
Sanitize escapes Unicode bidi/spoofing characters in every LLM- or web-influenced string field, mirroring ToolCall.SanitizeArguments. Call it before broadcasting or persisting the activity.
type ServiceConfig ¶
type ServiceConfig struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
APIKey string `json:"apiKey"`
OrgID string `json:"orgId"`
DefaultModel string `json:"defaultModel"`
APIURL string `json:"apiURL"`
Region string `json:"region"` // For AWS Bedrock region
// AWS IAM credentials for Bedrock (optional, takes precedence over APIKey)
AWSAccessKeyID string `json:"awsAccessKeyID"`
AWSSecretAccessKey string `json:"awsSecretAccessKey"`
// Vertex AI (GCP) configuration. Region is reused from the shared Region field.
// VertexAuthCredentials holds the service-account JSON; when empty, Bifrost
// falls back to Application Default Credentials / attached IAM role.
VertexProjectID string `json:"vertexProjectID"`
VertexProjectNumber string `json:"vertexProjectNumber"`
VertexAuthCredentials string `json:"vertexAuthCredentials"`
// Renaming the JSON field to inputTokenLimit would require a migration, leaving as is for now.
InputTokenLimit int `json:"tokenLimit"`
StreamingTimeoutSeconds int `json:"streamingTimeoutSeconds"`
// Otherwise known as maxTokens
OutputTokenLimit int `json:"outputTokenLimit"`
// UseResponsesAPI determines whether to use the new OpenAI Responses API
// Only applicable to OpenAI and OpenAI-compatible services
UseResponsesAPI bool `json:"useResponsesAPI"`
// FallbackServiceID is the ID of another service to fall back to when this
// service's provider/model fails (e.g. network error, rate limit, model
// unavailable). The fallback service's DefaultModel is used. Chains are
// followed (A→B→C) with cycle detection.
FallbackServiceID string `json:"fallbackServiceID,omitempty"`
// LoadTestMockConfig is raw JSON merged by loadtest.ParseProfile for ServiceTypeLoadTestMock.
// Nil, empty, or whitespace-only means the default read/search-heavy profile.
LoadTestMockConfig json.RawMessage `json:"loadTestMockConfig,omitempty"`
}
func ResolveFallbackChain ¶
func ResolveFallbackChain(primaryServiceID string, getServiceByID func(id string) (ServiceConfig, bool)) ([]ServiceConfig, error)
ResolveFallbackChain walks the fallback chain starting from the service identified by primaryServiceID, returning an ordered slice of fallback ServiceConfigs. A misconfigured chain — a cycle, or a fallback ID that is missing or invalid — returns an error so the problem surfaces at setup instead of silently leaving the bot without the configured fallback. A missing primary returns an empty chain; the caller surfaces that error when it resolves the primary itself.
type StreamGenerator ¶
type StreamGenerator struct {
// TotalTextSize is the total bytes of text to generate
TotalTextSize int
// ChunkSize is the size of each text chunk
ChunkSize int
// IncludeReasoning adds reasoning events before text events
IncludeReasoning bool
// IncludeToolCalls ends with tool calls instead of normal end event
IncludeToolCalls bool
// IncludeUsage adds a usage event before end
IncludeUsage bool
// IncludeAnnotations adds annotation events
IncludeAnnotations bool
}
StreamGenerator creates synthetic streams for benchmarking. It generates TextStreamResult with configurable event patterns.
func (*StreamGenerator) Generate ¶
func (g *StreamGenerator) Generate() *TextStreamResult
Generate creates a new TextStreamResult with synthetic events. The stream is generated in a goroutine and returned immediately.
type StructuredOutputFallbackWrapper ¶
type StructuredOutputFallbackWrapper struct {
// contains filtered or unexported fields
}
StructuredOutputFallbackWrapper wraps a LanguageModel and encapsulates the structured output capability decision. When structured output is enabled, requests pass through untouched and any JSON schema is sent natively to the provider. When disabled and a JSON schema is requested, the schema is stripped from the provider request and converted into a prompt-level system instruction, and markdown code fencing is stripped from non-streaming responses.
func NewStructuredOutputFallbackWrapper ¶
func NewStructuredOutputFallbackWrapper(llm LanguageModel, structuredOutputEnabled bool) *StructuredOutputFallbackWrapper
func (*StructuredOutputFallbackWrapper) ChatCompletion ¶
func (w *StructuredOutputFallbackWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
func (*StructuredOutputFallbackWrapper) ChatCompletionNoStream ¶
func (w *StructuredOutputFallbackWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
func (*StructuredOutputFallbackWrapper) CountTokens ¶
func (w *StructuredOutputFallbackWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
CountTokens applies the fallback so counts reflect the request actually sent.
func (*StructuredOutputFallbackWrapper) InputTokenLimit ¶
func (w *StructuredOutputFallbackWrapper) InputTokenLimit() int
func (*StructuredOutputFallbackWrapper) OutputTokenLimit ¶
func (w *StructuredOutputFallbackWrapper) OutputTokenLimit() int
type TextRange ¶ added in v2.7.0
TextRange is a half-open byte range in concatenated text segments, used to delete citation markers without moving text around intervening activity.
type TextStreamEvent ¶
TextStreamEvent represents an event in the text stream
type TextStreamResult ¶
type TextStreamResult struct {
Stream <-chan TextStreamEvent
}
TextStreamResult represents a stream of text events
func NewStreamFromString ¶
func NewStreamFromString(text string) *TextStreamResult
func (*TextStreamResult) ReadAll ¶
func (t *TextStreamResult) ReadAll() (string, error)
type TokenUsage ¶
type TokenUsage struct {
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CachedReadTokens int64 `json:"cached_read_tokens,omitempty"`
CachedWriteTokens int64 `json:"cached_write_tokens,omitempty"`
ReasoningTokens int64 `json:"reasoning_tokens,omitempty"`
Cost float64 `json:"cost,omitempty"`
}
TokenUsage represents token usage statistics for an LLM request. Cached, reasoning, and cost fields stay zero when the provider doesn't report them.
type TokenUsageLoggingWrapper ¶
type TokenUsageLoggingWrapper struct {
// contains filtered or unexported fields
}
TokenUsageLoggingWrapper wraps a LanguageModel to log token usage
func NewTokenUsageLoggingWrapper ¶
func NewTokenUsageLoggingWrapper(wrapped LanguageModel, botUsername string, sinks *TokenUsageSinks, metrics MetricsObserver) *TokenUsageLoggingWrapper
NewTokenUsageLoggingWrapper creates a wrapper using a shared sink controller.
func (*TokenUsageLoggingWrapper) ChatCompletion ¶
func (w *TokenUsageLoggingWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
ChatCompletion intercepts the streaming response to extract and log token usage
func (*TokenUsageLoggingWrapper) ChatCompletionNoStream ¶
func (w *TokenUsageLoggingWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
ChatCompletionNoStream uses the streaming method internally, so token usage logging happens automatically when ReadAll() processes the intercepted stream
func (*TokenUsageLoggingWrapper) CountTokens ¶
func (w *TokenUsageLoggingWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
CountTokens delegates to the wrapped model
func (*TokenUsageLoggingWrapper) InputTokenLimit ¶
func (w *TokenUsageLoggingWrapper) InputTokenLimit() int
InputTokenLimit delegates to the wrapped model
func (*TokenUsageLoggingWrapper) OutputTokenLimit ¶
func (w *TokenUsageLoggingWrapper) OutputTokenLimit() int
OutputTokenLimit delegates to the wrapped model
type TokenUsagePluginLogger ¶
TokenUsagePluginLogger is the logger interface used for plugin JSON logs.
type TokenUsageSinks ¶
type TokenUsageSinks struct {
// contains filtered or unexported fields
}
TokenUsageSinks stores shared sink state for token usage logging. Wrappers can read these atomically so config toggles do not require rebuilding bot wrappers.
func NewTokenUsageSinks ¶
func NewTokenUsageSinks(pluginLogger TokenUsagePluginLogger) *TokenUsageSinks
NewTokenUsageSinks creates a sink controller with the provided plugin logger.
func (*TokenUsageSinks) FileLogger ¶
func (s *TokenUsageSinks) FileLogger() *mlog.Logger
func (*TokenUsageSinks) LoggingEnabled ¶
func (s *TokenUsageSinks) LoggingEnabled() bool
func (*TokenUsageSinks) PluginLogger ¶
func (s *TokenUsageSinks) PluginLogger() TokenUsagePluginLogger
func (*TokenUsageSinks) SetFileEnabled ¶
func (s *TokenUsageSinks) SetFileEnabled(enabled bool)
func (*TokenUsageSinks) SetFileLogger ¶
func (s *TokenUsageSinks) SetFileLogger(logger *mlog.Logger)
func (*TokenUsageSinks) SetLoggingEnabled ¶
func (s *TokenUsageSinks) SetLoggingEnabled(enabled bool)
func (*TokenUsageSinks) SetPluginEnabled ¶
func (s *TokenUsageSinks) SetPluginEnabled(enabled bool)
type Tool ¶
type Tool struct {
Name string
Description string
Schema any
Resolver ToolResolver
// Title is an optional human-readable display name resolved from MCP
// metadata (title > annotations.title) and Unicode-sanitized at capture
// (mcp.UserClients.GetTools). Empty for built-in tools and MCP tools that
// do not declare one.
Title string
// ServerOrigin identifies the MCP server this tool came from (the BaseURL).
// Empty for built-in (non-MCP) tools. Used for auto-approval decisions.
ServerOrigin string
// UserInteraction marks a tool whose pending call is answered by the
// requesting user in the Mattermost UI instead of executed by the server;
// the Resolver is only an error backstop. Empty for normal tools.
UserInteraction string
// AutoExecute marks a built-in tool that runs without user approval, like
// the MCP dynamic-loading meta-tools. Reserve it for tools whose only side
// effect is scoped to the assistant's own response (e.g. CreateFile
// attaching a file to the reply post). Only honored for tools with an
// empty ServerOrigin — MCP tools must never auto-execute through this flag.
AutoExecute bool
// CallMetadata is forwarded to the tool implementation as MCP CallToolParams.Meta.
// It is invisible to the LLM, not part of the input schema, and not parsed from the
// model's arguments. Set it at scope-time via WithCallMetadata when callers need to
// plumb runtime/protocol info (e.g. before-hook keys) that the underlying server
// needs but the model shouldn't see or be able to manipulate.
CallMetadata map[string]any
}
Tool represents a function that can be called by the language model during a conversation.
Each tool has a name, description, and schema that defines its parameters. These are passed to the LLM for it to understand what capabilities it has. It is the Resolver function that implements the actual functionality.
The Schema field should contain a JSONSchema that defines the expected structure of the tool's arguments. The Resolver function receives the request context, conversation context, and parsed arguments, and returns either a result that will be passed to the LLM or an error.
func FilterMCPToolsByAllowlist ¶
FilterMCPToolsByAllowlist returns a new slice containing every built-in tool (empty ServerOrigin) plus every MCP tool whose (ServerOrigin, Name) pair is present in the allowlist map. Allowlist keys use the format "serverOrigin\x00toolName"; both the namespaced runtime name and the bare name (see BareMCPToolName) are checked, so persisted allowlists with legacy bare names continue to match.
An empty or nil allowlist drops every MCP tool while still keeping built-in tools. The input slice is never mutated. Use FilterMCPToolsByEnabledAllowlist for EnabledMCPTool wildcard semantics.
func FilterMCPToolsByEnabledAllowlist ¶
func FilterMCPToolsByEnabledAllowlist(tools []Tool, allowlist []EnabledMCPTool) []Tool
FilterMCPToolsByEnabledAllowlist filters a plain tool slice using configured MCP allowlist entries, including wildcard expansion and normalized origins.
func (Tool) WithBoundParams ¶
WithBoundParams creates a new Tool with parameters bound to fixed values. Bound parameters are: - Removed from the schema (LLM cannot see or manipulate them) - Automatically injected when the resolver is called
func (Tool) WithCallMetadata ¶
WithCallMetadata returns a copy of the tool with CallMetadata set. Use this to attach per-call MCP metadata (like before-hook keys) at scope-time without leaking it into the LLM-visible schema or making the resolver fish it out of llm.Context. Passing an empty map clears the field.
type ToolArgumentGetter ¶
type ToolAuthError ¶
type ToolAuthError struct {
ServerName string `json:"server_name"`
ServerOrigin string `json:"server_origin"`
AuthURL string `json:"auth_url"`
Error error `json:"error"`
}
ToolAuthError represents an authentication error that occurred during tool creation
type ToolCall ¶
type ToolCall struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Arguments json.RawMessage `json:"arguments"`
Result string `json:"result"`
Status ToolCallStatus `json:"status"`
MCPBareName string `json:"mcp_bare_name,omitempty"`
// Title is the resolved display name for MCP tools that declare one
// (title > annotations.title, resolved at capture). When empty the webapp
// prettifies the bare name. Visible to non-requesters like Name.
Title string `json:"title,omitempty"`
// UserInteraction mirrors Tool.UserInteraction so the webapp can render
// the matching interaction UI (e.g. a question card) for pending calls.
UserInteraction string `json:"user_interaction,omitempty"`
// WouldAutoExecute marks any pending call that passed the auto-execution
// policy. The webapp must not show approval controls for it; the server
// re-checks the policy before executing it on resume.
WouldAutoExecute bool `json:"would_auto_execute,omitempty"`
// ServerOrigin identifies the MCP server this tool came from (the BaseURL).
// Empty for built-in tools. Used for auto-approval decisions.
ServerOrigin string `json:"server_origin,omitempty"`
}
ToolCall represents a tool call. An empty result indicates that the tool has not yet been resolved.
func (*ToolCall) SanitizeArguments ¶
func (tc *ToolCall) SanitizeArguments()
SanitizeArguments sanitizes the Arguments field to prevent bidirectional text and other Unicode spoofing attacks. Also ensures Arguments is valid JSON (defaults to "{}" if empty/nil).
type ToolCallStatus ¶
type ToolCallStatus int
ToolCallStatus represents the current status of a tool call
const ( // ToolCallStatusPending indicates the tool is waiting for user approval/rejection ToolCallStatusPending ToolCallStatus = iota // ToolCallStatusAccepted indicates the user has accepted the tool call but it's not resolved yet ToolCallStatusAccepted // ToolCallStatusRejected indicates the user has rejected the tool call ToolCallStatusRejected // ToolCallStatusError indicates the tool call was accepted but errored during resolution ToolCallStatusError // ToolCallStatusSuccess indicates the tool call was accepted and resolved successfully ToolCallStatusSuccess // ToolCallStatusAutoApproved indicates the tool call was auto-approved and executed // by the MCP approved servers feature per admin configuration. // This status is set by the stream wrapper and consumed by the streaming layer // to skip the call-approval UI and proceed directly to result-sharing. ToolCallStatusAutoApproved )
type ToolCatalogContext ¶
type ToolCatalogContext struct {
// MCPDynamicToolLoading indicates this context uses strict MCP dynamic loading.
MCPDynamicToolLoading bool
// DisabledMCPServerOrigins contains per-user disabled MCP server origins that
// must be removed before strict registry construction.
DisabledMCPServerOrigins []string
// KeepMCPTool, when non-nil, is applied to MCP tools before strict registry
// construction and before flag-off visible MCP insertion.
KeepMCPTool func(Tool) bool
// PreloadedMCPTools contains exact-or-bare MCP tool selectors for internal
// predefined flows. They are selected only from the already-authorized MCP
// catalog and are request scoped.
PreloadedMCPTools []EnabledMCPTool
// InteractiveUserPresent indicates the requesting user is interactively
// present in Mattermost (DM or human channel mention) and can answer
// pending tool approvals. Tools that require a user response (see
// Tool.UserInteraction) are only cataloged when this is set.
InteractiveUserPresent bool
// ResponseFilesSupported indicates the current flow attaches
// ToolRuntime.CreatedFiles to the bot's streamed response post, so
// file-creating response tools (CreateFile) may be cataloged. Only
// conversation entry points that stream a response post set this.
ResponseFilesSupported bool
// SandboxFilesAttached is true when this turn's sandbox output will be
// attached automatically. The model cannot see provider file ids, so the
// prompt must tell it to copy shareable files into $OUTPUT_DIR.
SandboxFilesAttached bool
}
ToolCatalogContext holds request-scoped tool catalog build inputs.
type ToolInfo ¶
ToolInfo represents basic information about a tool without its full implementation. Used to inform LLMs about tools that are unavailable in the current context.
type ToolLookup ¶
ToolLookup describes how a tool call name resolved in a ToolStore.
type ToolResolver ¶
type ToolRuntimeContext ¶
type ToolRuntimeContext struct {
// MCPDynamicToolTelemetry receives low-cardinality dynamic MCP tool events.
MCPDynamicToolTelemetry MCPDynamicToolTelemetry
MCPDynamicToolSearchUsed bool
MCPDynamicLoadedToolNames map[string]bool
MCPDynamicSearchLoadCallSuccessRecorded map[string]bool
// CreatedFiles collects files created by tools during this turn for
// attachment to the response post.
CreatedFiles []CreatedFile
// SandboxFiles are provider files observed this request, in order, with
// the route that produced them. Populated only from server-tool activity,
// never from model input.
SandboxFiles []ProviderFileReference
// ResponseAttachmentBudget caps how many files response tools may create
// this turn. 0 means unset (full MaxPostAttachments budget); -1 means the
// response post has no room left. Set via SetResponseAttachmentBudget.
ResponseAttachmentBudget int
}
ToolRuntimeContext holds request-scoped tool runtime state that should not be rendered into the prompt.
func (*ToolRuntimeContext) AddCreatedFile ¶ added in v2.6.0
func (t *ToolRuntimeContext) AddCreatedFile(f CreatedFile)
func (*ToolRuntimeContext) AddSandboxFiles ¶ added in v2.7.0
func (t *ToolRuntimeContext) AddSandboxFiles(refs ...ProviderFileReference)
func (*ToolRuntimeContext) CreatedFilesList ¶ added in v2.6.0
func (t *ToolRuntimeContext) CreatedFilesList() []CreatedFile
func (*ToolRuntimeContext) MarkMCPDynamicToolLoaded ¶
func (t *ToolRuntimeContext) MarkMCPDynamicToolLoaded(name string)
func (*ToolRuntimeContext) MarkMCPDynamicToolSearch ¶
func (t *ToolRuntimeContext) MarkMCPDynamicToolSearch()
func (*ToolRuntimeContext) ObserveMCPDynamicToolEvent ¶
func (t *ToolRuntimeContext) ObserveMCPDynamicToolEvent(botName, event, result string)
func (*ToolRuntimeContext) ResponseAttachmentSlots ¶ added in v2.6.0
func (t *ToolRuntimeContext) ResponseAttachmentSlots() int
func (*ToolRuntimeContext) SetResponseAttachmentBudget ¶ added in v2.6.0
func (t *ToolRuntimeContext) SetResponseAttachmentBudget(remaining int)
func (*ToolRuntimeContext) ShouldRecordMCPDynamicSearchLoadCallSuccess ¶
func (t *ToolRuntimeContext) ShouldRecordMCPDynamicSearchLoadCallSuccess(name string) bool
type ToolStore ¶
type ToolStore struct {
// contains filtered or unexported fields
}
func NewNoTools ¶
func NewNoTools() *ToolStore
func NewToolStore ¶
func NewToolStore() *ToolStore
func (*ToolStore) AddAuthError ¶
func (s *ToolStore) AddAuthError(authError ToolAuthError)
AddAuthError adds an authentication error to the tool store
func (*ToolStore) GetAuthErrors ¶
func (s *ToolStore) GetAuthErrors() []ToolAuthError
GetAuthErrors returns all authentication errors collected during tool creation
func (*ToolStore) GetServerOrigin ¶
GetServerOrigin returns the ServerOrigin for a tool by name. Returns empty string if the tool is not found or has no server origin (built-in tools).
func (*ToolStore) GetToolsInfo ¶
GetToolsInfo returns basic information (name and description) about all tools in the store. This is useful for informing LLMs about tools that are available in other contexts (e.g., DM-only tools when in a channel).
func (*ToolStore) GetUnloadedMCPToolInfo ¶
func (*ToolStore) HasUnloadedMCPTools ¶
func (*ToolStore) IsUnloadedMCPTool ¶
func (*ToolStore) KeepToolsIf ¶
KeepToolsIf removes tools for which keep returns false.
func (*ToolStore) LoadMCPTools ¶
LoadMCPTools moves the named tools from the unloaded MCP set into the active tool store, returning the tools that were loaded. Names must be exact (namespaced) registry names; bare names are ignored.
func (*ToolStore) LookupTool ¶
func (s *ToolStore) LookupTool(name, serverOrigin string) (ToolLookup, bool)
LookupTool resolves exact names and unique bare MCP names, optionally scoped to a server origin.
func (*ToolStore) RemoveToolsByServerOrigin ¶
RemoveToolsByServerOrigin removes all tools whose ServerOrigin matches any of the provided origins. This is used for user-disabled provider filtering in Copilot DM contexts.
func (*ToolStore) ResolveTool ¶
func (*ToolStore) RetainOnlyMCPTools ¶
func (s *ToolStore) RetainOnlyMCPTools(allowlist []EnabledMCPTool)
RetainOnlyMCPTools filters the tool store to only retain MCP tools whose (ServerOrigin, Name) pair appears in the allowlist. Built-in tools (those with empty ServerOrigin) are never removed by this method.
An empty or nil allowlist removes all MCP tools. Callers that want to keep every MCP tool (e.g. agents with AutoEnableNewMCPTools=true) should skip calling this method entirely.
func (*ToolStore) SetUnloadedMCPTools ¶
type TruncationWrapper ¶
type TruncationWrapper struct {
// contains filtered or unexported fields
}
func NewLLMTruncationWrapper ¶
func NewLLMTruncationWrapper(llm LanguageModel) *TruncationWrapper
func (*TruncationWrapper) ChatCompletion ¶
func (w *TruncationWrapper) ChatCompletion(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (*TextStreamResult, error)
func (*TruncationWrapper) ChatCompletionNoStream ¶
func (w *TruncationWrapper) ChatCompletionNoStream(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (string, error)
func (*TruncationWrapper) CountTokens ¶
func (w *TruncationWrapper) CountTokens(ctx context.Context, request CompletionRequest, opts ...LanguageModelOption) (int, error)
func (*TruncationWrapper) InputTokenLimit ¶
func (w *TruncationWrapper) InputTokenLimit() int
func (*TruncationWrapper) OutputTokenLimit ¶
func (w *TruncationWrapper) OutputTokenLimit() int
type TurnSegment ¶ added in v2.7.0
type TurnSegment struct {
Kind string
Text string
Signature string
// ServerToolID looks up the payload in the latest activity snapshot.
// The provider updates invocations in place, so the segment only stores the id.
ServerToolID string
// contains filtered or unexported fields
}
TurnSegment is one piece of assistant output in arrival order.
type TurnSequence ¶ added in v2.7.0
type TurnSequence struct {
// contains filtered or unexported fields
}
TurnSequence records assistant output in arrival order. Grouping by kind (all text, then all activity) reorders interleaved narration and sandbox runs so the bot appears to describe work before doing it.
func (*TurnSequence) AppendReasoning ¶ added in v2.7.0
func (s *TurnSequence) AppendReasoning(text string)
AppendReasoning extends the current unfinalized thinking segment.
func (*TurnSequence) AppendText ¶ added in v2.7.0
func (s *TurnSequence) AppendText(text string)
AppendText extends the current text segment when the previous arrival was also text.
func (*TurnSequence) FinishReasoning ¶ added in v2.7.0
func (s *TurnSequence) FinishReasoning(data ReasoningData)
FinishReasoning closes the current thinking segment. Later reasoning starts a new one.
func (*TurnSequence) HasText ¶ added in v2.7.0
func (s *TurnSequence) HasText() bool
HasText reports whether any response text was recorded.
func (*TurnSequence) RecordServerTools ¶ added in v2.7.0
func (s *TurnSequence) RecordServerTools(uses []ServerToolUse)
RecordServerTools positions each new invocation at first appearance. Snapshots are cumulative; later updates must not move an already-placed id.
func (*TurnSequence) RemoveTextRanges ¶ added in v2.7.0
func (s *TurnSequence) RemoveTextRanges(original string, ranges []TextRange) bool
RemoveTextRanges deletes ranges from concatenated text in place so activity between text segments keeps its position. original must match Text() exactly.
func (*TurnSequence) Reset ¶ added in v2.7.0
func (s *TurnSequence) Reset()
Reset drops every recorded segment.
func (*TurnSequence) Segments ¶ added in v2.7.0
func (s *TurnSequence) Segments() []TurnSegment
Segments returns the recorded segments in arrival order.
func (*TurnSequence) Text ¶ added in v2.7.0
func (s *TurnSequence) Text() string
Text concatenates response-text segments, excluding reasoning and activity.
type UserAccessLevel ¶
type UserAccessLevel int
const ( UserAccessLevelAll UserAccessLevel = iota UserAccessLevelAllow UserAccessLevelBlock UserAccessLevelNone )
Source Files
¶
- annotations.go
- completion_request.go
- composition.go
- configuration.go
- context.go
- estimate.go
- json_sanitize.go
- language_model.go
- loadtest_validation.go
- logging.go
- model_fetcher.go
- prompts.go
- provider_error.go
- provider_services.go
- providers.go
- service_types.go
- stream.go
- stream_generator.go
- string_indices.go
- structured_output_fallback.go
- token_tracking.go
- token_usage_fields.go
- token_usage_sinks.go
- tool_retry.go
- tools.go
- transport.go
- truncation.go
- turn_sequence.go