Documentation
¶
Index ¶
- Constants
- func NewInternalError(err error) error
- func NewTextCompletionMessage(role Role, content string) *aiv1.CompletionMessage
- func RegisterTool[In, Out any](s *Runner, t Tool[In, Out])
- func WithSession(ctx context.Context, s *Session) context.Context
- type AddMessageOptions
- type AnalystAgent
- type AnalystAgentArgs
- type AnalystAgentResult
- type BaseSession
- func (s *BaseSession) CatalogSession() *drivers.AISession
- func (s *BaseSession) Claims() *runtime.SecurityClaims
- func (s *BaseSession) ExpandMessages(msgs []*Message, fn func(m *Message) []*Message) []*Message
- func (s *BaseSession) Flush(ctx context.Context) error
- func (s *BaseSession) ID() string
- func (s *BaseSession) InstanceID() string
- func (s *BaseSession) LatestMessage(predicates ...Predicate) (*Message, bool)
- func (s *BaseSession) LatestRootCall() *Message
- func (s *BaseSession) Message(predicates ...Predicate) (*Message, bool)
- func (s *BaseSession) Messages(predicates ...Predicate) []*Message
- func (s *BaseSession) MessagesWithChildren(predicates ...Predicate) []*Message
- func (s *BaseSession) MessagesWithDescendents(predicates ...Predicate) []*Message
- func (s *BaseSession) MessagesWithResults(predicates ...Predicate) []*Message
- func (s *BaseSession) NextIndex() int
- func (s *BaseSession) ProjectInstructions() string
- func (s *BaseSession) SetLLM(acquireLLM func(ctx context.Context) (drivers.AIService, func(), error))
- func (s *BaseSession) Subscribe() chan *Message
- func (s *BaseSession) Title() string
- func (s *BaseSession) Unsubscribe(ch chan *Message)
- func (s *BaseSession) UpdateTitle(ctx context.Context, title string) error
- func (s *BaseSession) UpdateUserAgent(ctx context.Context, userAgent string) error
- func (s *BaseSession) WithParent(messageID string) *Session
- type CallOptions
- type CallResult
- type CallToolOptions
- type CompiledTool
- type CompleteOptions
- type CreateChart
- type CreateChartArgs
- type CreateChartResult
- type DevelopMetricsView
- type DevelopMetricsViewArgs
- type DevelopMetricsViewResult
- type DevelopModel
- type DevelopModelArgs
- type DevelopModelResult
- type DeveloperAgent
- type DeveloperAgentArgs
- type DeveloperAgentResult
- type GetMetricsView
- type GetMetricsViewArgs
- type GetMetricsViewResult
- type InternalError
- type LLMMarshaler
- type ListFiles
- type ListFilesArgs
- type ListFilesResult
- type ListMetricsViews
- type ListMetricsViewsArgs
- type ListMetricsViewsResult
- type Message
- type MessageContentType
- type MessageType
- type Predicate
- type QueryMetricsView
- type QueryMetricsViewArgs
- type QueryMetricsViewResult
- type QueryMetricsViewSummary
- type QueryMetricsViewSummaryArgs
- type QueryMetricsViewSummaryResult
- type ReadFile
- type ReadFileArgs
- type ReadFileResult
- type Role
- type RouterAgent
- type RouterAgentArgs
- type RouterAgentResult
- type Runner
- type SearchFiles
- type SearchFilesArgs
- type SearchFilesResult
- type SearchMatch
- type Session
- func (s *Session) AddMessage(opts *AddMessageOptions) *Message
- func (s *Session) Call(ctx context.Context, opts *CallOptions) (*CallResult, error)
- func (s *Session) CallTool(ctx context.Context, role Role, toolName string, out, args any) (*CallResult, error)
- func (s *Session) CallToolWithOptions(ctx context.Context, opts *CallToolOptions) (*CallResult, error)
- func (s *Session) Complete(ctx context.Context, name string, out any, opts *CompleteOptions) error
- func (s *Session) MCPServer(ctx context.Context) *mcp.Server
- func (s *Session) NewCompletionMessage(m *Message) (*aiv1.CompletionMessage, error)
- func (s *Session) NewCompletionMessages(msgs []*Message) []*aiv1.CompletionMessage
- func (s *Session) RootID() string
- func (s *Session) Tool(toolName string) (*CompiledTool, bool)
- func (s *Session) UnmarshalMessageContent(m *Message) (any, error)
- type SessionOptions
- type Tool
- type WriteFile
- type WriteFileArgs
- type WriteFileResult
Constants ¶
const AnalystAgentName = "analyst_agent"
const CreateChartName = "create_chart"
const DevelopMetricsViewName = "develop_metrics_view"
const DevelopModelName = "develop_model"
const DeveloperAgentName = "developer_agent"
const GetMetricsViewName = "get_metrics_view"
const ListFilesName = "list_files"
const ListMetricsViewsName = "list_metrics_views"
const QueryMetricsViewName = "query_metrics_view"
const QueryMetricsViewSummaryName = "query_metrics_view_summary"
const ReadFileName = "read_file"
const RouterAgentName = "router_agent"
const SearchFilesName = "search_files"
const WriteFileName = "write_file"
Variables ¶
This section is empty.
Functions ¶
func NewInternalError ¶
NewInternalError creates a new internal error. See InternalError for details.
func NewTextCompletionMessage ¶
func NewTextCompletionMessage(role Role, content string) *aiv1.CompletionMessage
NewTextCompletionMessage is a utility function for creating a text completion message.
func RegisterTool ¶
RegisterTool registers a new tool with the Runner.
Types ¶
type AddMessageOptions ¶
type AddMessageOptions struct {
Role Role
Type MessageType
Tool string
ContentType MessageContentType
Content string
}
AddMessageOptions provides options for Session.AddMessage.
type AnalystAgent ¶
func (*AnalystAgent) CheckAccess ¶
func (t *AnalystAgent) CheckAccess(ctx context.Context) (bool, error)
func (*AnalystAgent) Handler ¶
func (t *AnalystAgent) Handler(ctx context.Context, args *AnalystAgentArgs) (*AnalystAgentResult, error)
func (*AnalystAgent) Spec ¶
func (t *AnalystAgent) Spec() *mcp.Tool
type AnalystAgentArgs ¶
type AnalystAgentArgs struct {
Prompt string `json:"prompt"`
Explore string `` /* 139-byte string literal not displayed */
Dimensions []string `` /* 151-byte string literal not displayed */
Measures []string `` /* 143-byte string literal not displayed */
Where *metricsview.Expression `json:"where" yaml:"where" jsonschema:"Optional filter for queries. If provided, this filter will be applied to all queries."`
TimeStart time.Time `` /* 134-byte string literal not displayed */
TimeEnd time.Time `` /* 128-byte string literal not displayed */
}
func (*AnalystAgentArgs) ToLLM ¶
func (a *AnalystAgentArgs) ToLLM() *aiv1.ContentBlock
type AnalystAgentResult ¶
type AnalystAgentResult struct {
Response string `json:"response"`
}
func (*AnalystAgentResult) ToLLM ¶
func (r *AnalystAgentResult) ToLLM() *aiv1.ContentBlock
type BaseSession ¶
type BaseSession struct {
// contains filtered or unexported fields
}
BaseSession contains the session implementation that is not specific to the current call.
func (*BaseSession) CatalogSession ¶
func (s *BaseSession) CatalogSession() *drivers.AISession
func (*BaseSession) Claims ¶
func (s *BaseSession) Claims() *runtime.SecurityClaims
func (*BaseSession) ExpandMessages ¶
func (s *BaseSession) ExpandMessages(msgs []*Message, fn func(m *Message) []*Message) []*Message
func (*BaseSession) ID ¶
func (s *BaseSession) ID() string
func (*BaseSession) InstanceID ¶
func (s *BaseSession) InstanceID() string
func (*BaseSession) LatestMessage ¶
func (s *BaseSession) LatestMessage(predicates ...Predicate) (*Message, bool)
func (*BaseSession) LatestRootCall ¶
func (s *BaseSession) LatestRootCall() *Message
func (*BaseSession) Message ¶
func (s *BaseSession) Message(predicates ...Predicate) (*Message, bool)
func (*BaseSession) Messages ¶
func (s *BaseSession) Messages(predicates ...Predicate) []*Message
func (*BaseSession) MessagesWithChildren ¶
func (s *BaseSession) MessagesWithChildren(predicates ...Predicate) []*Message
func (*BaseSession) MessagesWithDescendents ¶
func (s *BaseSession) MessagesWithDescendents(predicates ...Predicate) []*Message
func (*BaseSession) MessagesWithResults ¶
func (s *BaseSession) MessagesWithResults(predicates ...Predicate) []*Message
func (*BaseSession) NextIndex ¶
func (s *BaseSession) NextIndex() int
func (*BaseSession) ProjectInstructions ¶
func (s *BaseSession) ProjectInstructions() string
func (*BaseSession) Subscribe ¶
func (s *BaseSession) Subscribe() chan *Message
func (*BaseSession) Title ¶
func (s *BaseSession) Title() string
func (*BaseSession) Unsubscribe ¶
func (s *BaseSession) Unsubscribe(ch chan *Message)
func (*BaseSession) UpdateTitle ¶
func (s *BaseSession) UpdateTitle(ctx context.Context, title string) error
func (*BaseSession) UpdateUserAgent ¶
func (s *BaseSession) UpdateUserAgent(ctx context.Context, userAgent string) error
func (*BaseSession) WithParent ¶
func (s *BaseSession) WithParent(messageID string) *Session
type CallOptions ¶
type CallOptions struct {
Role Role
Name string
Unwrap bool
Out any
Args any
Handler func(context.Context) (any, error)
}
CallOptions provides options for Session.Call.
type CallResult ¶
CallResult contains the messages created during a tool call.
type CallToolOptions ¶
CallToolOptions provides options for Session.CallTool.
type CompiledTool ¶
type CompiledTool struct {
Name string
Spec *mcp.Tool
CheckAccess func(context.Context) (bool, error)
UnmarshalArgs func(content string) (any, error)
UnmarshalResult func(content string) (any, error)
JSONHandler func(ctx context.Context, input json.RawMessage) (json.RawMessage, error)
RegisterWithMCPServer func(srv *mcp.Server)
}
CompiledTool is the internal representation of a registered tool.
type CompleteOptions ¶
type CompleteOptions struct {
Messages []*aiv1.CompletionMessage
Tools []string
MaxIterations int
// The complete loop will add intermediate messages for LLM thinking and tool calls to session under the current call.
// In some cases, it's desirable to capture these intermediate messages in the parent call's context, in other cases it's better to isolate them and only expose the final result to the parent context.
// When UnwrapCall is true, we run the completion loop within the current call, otherwise we wrap the complete loop in a new call to isolate internal messages.
UnwrapCall bool
}
CompleteOptions provides options for Session.Complete.
type CreateChart ¶
func (*CreateChart) CheckAccess ¶
func (t *CreateChart) CheckAccess(ctx context.Context) (bool, error)
func (*CreateChart) Handler ¶
func (t *CreateChart) Handler(ctx context.Context, args CreateChartArgs) (*CreateChartResult, error)
func (*CreateChart) Spec ¶
func (t *CreateChart) Spec() *mcp.Tool
type CreateChartArgs ¶
type CreateChartResult ¶
type DevelopMetricsView ¶
func (*DevelopMetricsView) CheckAccess ¶
func (t *DevelopMetricsView) CheckAccess(ctx context.Context) (bool, error)
func (*DevelopMetricsView) Handler ¶
func (t *DevelopMetricsView) Handler(ctx context.Context, args *DevelopMetricsViewArgs) (*DevelopMetricsViewResult, error)
func (*DevelopMetricsView) Spec ¶
func (t *DevelopMetricsView) Spec() *mcp.Tool
type DevelopMetricsViewArgs ¶
type DevelopMetricsViewArgs struct {
Path string `json:"path" jsonschema:"The path of a .yaml file in which to create or update a Rill metrics view definition."`
Prompt string `json:"prompt" jsonschema:"Optional description of changes to make if editing an existing metrics view."`
Model string `json:"model" jsonschema:"Optional Rill model to derive from if creating a new metrics view."`
}
type DevelopMetricsViewResult ¶
type DevelopMetricsViewResult struct {
MetricsViewName string `json:"metrics_view_name" jsonschema:"The name of the developed Rill metrics view."`
}
type DevelopModel ¶
func (*DevelopModel) CheckAccess ¶
func (t *DevelopModel) CheckAccess(ctx context.Context) (bool, error)
func (*DevelopModel) Handler ¶
func (t *DevelopModel) Handler(ctx context.Context, args *DevelopModelArgs) (*DevelopModelResult, error)
func (*DevelopModel) Spec ¶
func (t *DevelopModel) Spec() *mcp.Tool
type DevelopModelArgs ¶
type DevelopModelResult ¶
type DevelopModelResult struct {
ModelName string `json:"model_name" jsonschema:"The name of the developed Rill model."`
}
type DeveloperAgent ¶
func (*DeveloperAgent) CheckAccess ¶
func (t *DeveloperAgent) CheckAccess(ctx context.Context) (bool, error)
func (*DeveloperAgent) Handler ¶
func (t *DeveloperAgent) Handler(ctx context.Context, args *DeveloperAgentArgs) (*DeveloperAgentResult, error)
func (*DeveloperAgent) Spec ¶
func (t *DeveloperAgent) Spec() *mcp.Tool
type DeveloperAgentArgs ¶
type DeveloperAgentArgs struct {
Prompt string `json:"prompt" jsonschema:"User prompt for the developer agent."`
InitProject bool `` /* 243-byte string literal not displayed */
CurrentFilePath string `json:"current_file_path,omitempty" jsonschema:"Optional path to the file that the user is currently viewing/editing."`
}
type DeveloperAgentResult ¶
type DeveloperAgentResult struct {
Response string `json:"response"`
}
type GetMetricsView ¶
func (*GetMetricsView) CheckAccess ¶
func (t *GetMetricsView) CheckAccess(ctx context.Context) (bool, error)
func (*GetMetricsView) Handler ¶
func (t *GetMetricsView) Handler(ctx context.Context, args *GetMetricsViewArgs) (*GetMetricsViewResult, error)
func (*GetMetricsView) Spec ¶
func (t *GetMetricsView) Spec() *mcp.Tool
type GetMetricsViewArgs ¶
type GetMetricsViewArgs struct {
MetricsView string `json:"metrics_view" jsonschema:"Name of the metrics view"`
}
type GetMetricsViewResult ¶
type InternalError ¶
type InternalError struct {
// contains filtered or unexported fields
}
InternalError represents an internal error in a tool call. This is needed because by default, downstream logic (such as the MCP middleware) treats errors returned from tool handlers as user errors, not internal errors.
func (InternalError) Error ¶
func (e InternalError) Error() string
Error implements the error interface.
type LLMMarshaler ¶
type LLMMarshaler interface {
ToLLM() *aiv1.ContentBlock
}
LLMMarshaler is an interface for tool args and results types that want to customize their serialization to LLM content blocks. It is not used for tool calls/results invoked by the assistant, only for user-invoked calls/results.
type ListFiles ¶
func (*ListFiles) Handler ¶
func (t *ListFiles) Handler(ctx context.Context, args *ListFilesArgs) (*ListFilesResult, error)
type ListFilesArgs ¶
type ListFilesArgs struct{}
type ListFilesResult ¶
type ListMetricsViews ¶
func (*ListMetricsViews) CheckAccess ¶
func (t *ListMetricsViews) CheckAccess(ctx context.Context) (bool, error)
func (*ListMetricsViews) Handler ¶
func (t *ListMetricsViews) Handler(ctx context.Context, args *ListMetricsViewsArgs) (*ListMetricsViewsResult, error)
func (*ListMetricsViews) Spec ¶
func (t *ListMetricsViews) Spec() *mcp.Tool
type ListMetricsViewsArgs ¶
type ListMetricsViewsArgs struct{}
type ListMetricsViewsResult ¶
type Message ¶
type Message struct {
// ID is unique for each message.
ID string `json:"id" yaml:"id"`
// ParentID is the ID of the parent message, usually the current tool call.
ParentID string `json:"parent_id" yaml:"parent_id"`
// SessionID is the ID of the session this message belongs to.
SessionID string `json:"session_id" yaml:"session_id"`
// Time the message was created.
Time time.Time `json:"time" yaml:"time"`
// Index of the message in the session. Used to order messages returned at the same time.
Index int `json:"index" yaml:"index"`
// Role is the actor that created the message.
Role Role `json:"role" yaml:"role"`
// Type is the type of the message.
// For any given call, there will be only one "result" or "error" message.
Type MessageType `json:"type" yaml:"type"`
// Tool is the name of the tool that emitted the message, if any.
Tool string `json:"tool"`
// ContentType is the type of the Content string.
ContentType MessageContentType `json:"content_type" yaml:"content_type"`
// Content is the content of the message.
Content string `json:"content" yaml:"content"`
// contains filtered or unexported fields
}
Message represents a message in an AI session. Unlike lower-level LLM messages, the messages here include a call hierarchy, enabling tracking of calls and results inside tool calls.
Mental model: - Messages represent user input, tool calls/results, LLM thinking, LLM responses. - Messages can be called by users, deterministic code, or LLMs. - LLM invocations retrieve messages from current scope for context.
type MessageContentType ¶
type MessageContentType string
MessageContentType is the type of content contained in a message.
const ( MessageContentTypeText MessageContentType = "text" MessageContentTypeJSON MessageContentType = "json" MessageContentTypeError MessageContentType = "error" )
type MessageType ¶
type MessageType string
MessageType is the type of message being sent.
const ( MessageTypeCall MessageType = "call" MessageTypeProgress MessageType = "progress" MessageTypeResult MessageType = "result" )
type Predicate ¶
func FilterByID ¶
func FilterByParent ¶
func FilterByRoot ¶
func FilterByRoot() Predicate
func FilterByTool ¶
func FilterByType ¶
func FilterByType(typ MessageType) Predicate
type QueryMetricsView ¶
func (*QueryMetricsView) CheckAccess ¶
func (t *QueryMetricsView) CheckAccess(ctx context.Context) (bool, error)
func (*QueryMetricsView) Handler ¶
func (t *QueryMetricsView) Handler(ctx context.Context, args QueryMetricsViewArgs) (*QueryMetricsViewResult, error)
func (*QueryMetricsView) Spec ¶
func (t *QueryMetricsView) Spec() *mcp.Tool
type QueryMetricsViewArgs ¶
type QueryMetricsViewResult ¶
type QueryMetricsViewSummary ¶
func (*QueryMetricsViewSummary) CheckAccess ¶
func (t *QueryMetricsViewSummary) CheckAccess(ctx context.Context) (bool, error)
func (*QueryMetricsViewSummary) Handler ¶
func (t *QueryMetricsViewSummary) Handler(ctx context.Context, args *QueryMetricsViewSummaryArgs) (*QueryMetricsViewSummaryResult, error)
func (*QueryMetricsViewSummary) Spec ¶
func (t *QueryMetricsViewSummary) Spec() *mcp.Tool
type QueryMetricsViewSummaryArgs ¶
type QueryMetricsViewSummaryArgs struct {
MetricsView string `json:"metrics_view" jsonschema:"Name of the metrics view"`
}
type ReadFile ¶
func (*ReadFile) Handler ¶
func (t *ReadFile) Handler(ctx context.Context, args *ReadFileArgs) (*ReadFileResult, error)
type ReadFileArgs ¶
type ReadFileArgs struct {
Path string `json:"path" jsonschema:"The path of the file to read"`
}
type ReadFileResult ¶
type ReadFileResult struct {
Contents string
}
type RouterAgent ¶
RouterAgent accepts a human prompt and related context, determines which agent is best suited to handling it, and invokes that agent. It is usually the entrypoint for processing human completion requests.
func (*RouterAgent) CheckAccess ¶
func (t *RouterAgent) CheckAccess(ctx context.Context) (bool, error)
func (*RouterAgent) Handler ¶
func (t *RouterAgent) Handler(ctx context.Context, args *RouterAgentArgs) (*RouterAgentResult, error)
func (*RouterAgent) Spec ¶
func (t *RouterAgent) Spec() *mcp.Tool
type RouterAgentArgs ¶
type RouterAgentArgs struct {
Prompt string `json:"prompt" jsonschema:"The user's prompt to be routed."`
Agent string `` /* 131-byte string literal not displayed */
AnalystAgentArgs *AnalystAgentArgs `` /* 136-byte string literal not displayed */
DeveloperAgentArgs *DeveloperAgentArgs `` /* 142-byte string literal not displayed */
SkipHandoff bool `` /* 158-byte string literal not displayed */
}
type RouterAgentResult ¶
type Runner ¶
type Runner struct {
Runtime *runtime.Runtime
Activity *activity.Client
Tools map[string]*CompiledTool
}
Runner tracks available tools and manages the lifecycle of AI sessions.
type SearchFiles ¶
func (*SearchFiles) CheckAccess ¶
func (t *SearchFiles) CheckAccess(ctx context.Context) (bool, error)
func (*SearchFiles) Handler ¶
func (t *SearchFiles) Handler(ctx context.Context, args *SearchFilesArgs) (*SearchFilesResult, error)
func (*SearchFiles) Spec ¶
func (t *SearchFiles) Spec() *mcp.Tool
type SearchFilesArgs ¶
type SearchFilesArgs struct {
Pattern string `json:"pattern" jsonschema:"The pattern to search for. Supports regular expressions."`
CaseSensitive bool `json:"case_sensitive,omitempty" jsonschema:"Whether the search should be case-sensitive. Defaults to false."`
GlobPattern string `` /* 152-byte string literal not displayed */
}
type SearchFilesResult ¶
type SearchFilesResult struct {
Matches []SearchMatch `json:"matches"`
}
type SearchMatch ¶
type Session ¶
type Session struct {
*BaseSession
ParentID string
}
Session wraps a BaseSession with a reference to the current call's parent message.
func GetSession ¶
GetSession retrieves a session from a context.
func (*Session) AddMessage ¶
func (s *Session) AddMessage(opts *AddMessageOptions) *Message
AddMessage adds a message linked to the current session's parent call.
func (*Session) Call ¶
func (s *Session) Call(ctx context.Context, opts *CallOptions) (*CallResult, error)
Call is the primary implementation for execution of tool calls. NOTE: This will be the primary implementation site for durable execution.
func (*Session) CallTool ¶
func (s *Session) CallTool(ctx context.Context, role Role, toolName string, out, args any) (*CallResult, error)
CallTool is a convenience wrapper around CallToolWithOptions that makes a normal assistant tool call.
func (*Session) CallToolWithOptions ¶
func (s *Session) CallToolWithOptions(ctx context.Context, opts *CallToolOptions) (*CallResult, error)
CallToolWithOptions runs a tool call in the current session and adds it, its result, and all messages from nested calls to the session.
func (*Session) Complete ¶
Complete runs LLM completions. If tools are provided, it runs a completion loop involving multiple LLM invocations. If the output pointer is not a string and not nil, it infers the output schema using reflection and instructs the LLM to produce structured output.
func (*Session) MCPServer ¶
MCPServer returns a new MCP server scoped to the current session. Since it is scoped to the session, a new MCP server should be created for each client connection. Using a separate MCP server for each client enables tailoring the server's instructions and available tools to the end user's claims.
func (*Session) NewCompletionMessage ¶
func (s *Session) NewCompletionMessage(m *Message) (*aiv1.CompletionMessage, error)
NewCompletionMessage converts the message to an aiv1.CompletionMessage
func (*Session) NewCompletionMessages ¶
func (s *Session) NewCompletionMessages(msgs []*Message) []*aiv1.CompletionMessage
NewCompletionMessages is a utility function for creating a list of completion messages from a list of session messages. NOTE: To support chaining, it panics on serialization errors. TODO: Move to a better chaining setup that enables error propagation.
type SessionOptions ¶
type SessionOptions struct {
InstanceID string
SessionID string
CreateIfNotExists bool
Claims *runtime.SecurityClaims
UserAgent string
}
SessionOptions provides options for initializing a new session.
type Tool ¶
type Tool[In, Out any] interface { Spec() *mcp.Tool CheckAccess(context.Context) (bool, error) Handler(ctx context.Context, args In) (Out, error) }
Tool is an interface for an AI tool.
type WriteFile ¶
func (*WriteFile) Handler ¶
func (t *WriteFile) Handler(ctx context.Context, args *WriteFileArgs) (*WriteFileResult, error)
type WriteFileArgs ¶
type WriteFileResult ¶
type WriteFileResult struct {
Diff string `json:"diff,omitempty" jsonschema:"Diff of the file contents."`
IsNewFile bool `json:"is_new_file,omitempty" jsonschema:"Indicates if the tool created a new file."`
Resources []map[string]any `json:"resources,omitempty" jsonschema:"The Rill resources declared in the file, if any."`
ParseError string `json:"parse_error,omitempty" jsonschema:"Parse error encountered when parsing the file, if any."`
}