pkg/ui/blocks.go (126 lines of code) (raw):
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ui
// AgentTextBlock is used to render agent textual responses
type AgentTextBlock struct {
doc *Document
// text is populated with the agent text output
text string
// Color is the foreground color of the text
Color ColorValue
// streaming is true if we are still streaming results in
streaming bool
}
func NewAgentTextBlock() *AgentTextBlock {
return &AgentTextBlock{}
}
func (b *AgentTextBlock) attached(doc *Document) {
b.doc = doc
}
func (b *AgentTextBlock) Document() *Document {
return b.doc
}
func (b *AgentTextBlock) Text() string {
return b.text
}
func (b *AgentTextBlock) Streaming() bool {
return b.streaming
}
func (b *AgentTextBlock) SetStreaming(streaming bool) *AgentTextBlock {
b.streaming = streaming
b.doc.blockChanged(b)
return b
}
func (b *AgentTextBlock) SetColor(color ColorValue) *AgentTextBlock {
b.Color = color
b.doc.blockChanged(b)
return b
}
func (b *AgentTextBlock) SetText(agentText string) *AgentTextBlock {
b.text = agentText
b.doc.blockChanged(b)
return b
}
func (b *AgentTextBlock) AppendText(text string) *AgentTextBlock {
b.text = b.text + text
b.doc.blockChanged(b)
return b
}
// FunctionCallRequestBlock is used to render the LLM's request to invoke a function
type FunctionCallRequestBlock struct {
doc *Document
// text is populated if this is agent text output
text string
}
func NewFunctionCallRequestBlock() *FunctionCallRequestBlock {
return &FunctionCallRequestBlock{}
}
func (b *FunctionCallRequestBlock) attached(doc *Document) {
b.doc = doc
}
func (b *FunctionCallRequestBlock) Document() *Document {
return b.doc
}
func (b *FunctionCallRequestBlock) Text() string {
return b.text
}
func (b *FunctionCallRequestBlock) SetText(agentText string) *FunctionCallRequestBlock {
b.text = agentText
b.doc.blockChanged(b)
return b
}
// ErrorBlock is used to render an error condition
type ErrorBlock struct {
doc *Document
// text is populated if this is agent text output
text string
}
func NewErrorBlock() *ErrorBlock {
return &ErrorBlock{}
}
func (b *ErrorBlock) attached(doc *Document) {
b.doc = doc
}
func (b *ErrorBlock) Document() *Document {
return b.doc
}
func (b *ErrorBlock) Text() string {
return b.text
}
func (b *ErrorBlock) SetText(agentText string) *ErrorBlock {
b.text = agentText
b.doc.blockChanged(b)
return b
}
// InputTextBlock is used to prompt for user input
type InputTextBlock struct {
doc *Document
// text is populated when we have input from the user
text Observable[string]
}
func NewInputTextBlock() *InputTextBlock {
return &InputTextBlock{}
}
func (b *InputTextBlock) attached(doc *Document) {
b.doc = doc
}
func (b *InputTextBlock) Document() *Document {
return b.doc
}
func (b *InputTextBlock) Observable() *Observable[string] {
return &b.text
}
// InputOptionBlock is used to prompt for a selection from multiple choices
type InputOptionBlock struct {
doc *Document
// Options are the valid options that can be chosen
Options []string
// Prompt is the prompt to show the user
Prompt string
// text is populated when we have input from the user
text Observable[string]
}
func NewInputOptionBlock() *InputOptionBlock {
return &InputOptionBlock{}
}
func (b *InputOptionBlock) SetOptions(options []string) *InputOptionBlock {
b.Options = options
return b
}
// SetPrompt sets the prompt to show the user
func (b *InputOptionBlock) SetPrompt(prompt string) *InputOptionBlock {
b.Prompt = prompt
return b
}
func (b *InputOptionBlock) attached(doc *Document) {
b.doc = doc
}
func (b *InputOptionBlock) Document() *Document {
return b.doc
}
func (b *InputOptionBlock) Observable() *Observable[string] {
return &b.text
}