Interactive Spring Shell-based command-line interface for the Embabel Agent platform, providing terminal interaction, chat sessions, and agent management commands.
The shell module provides customizable prompt providers that control the appearance and behavior of the command-line prompt. This includes a default provider and multiple themed personality providers.
The Spring Shell interface for providing custom prompts.
interface PromptProvider {
fun getPrompt(): AttributedString
}Returns: AttributedString with styled prompt text
This interface is from the Spring Shell framework (org.springframework.shell.jline.PromptProvider).
Simple vanilla prompt provider showing "embabel> " in yellow.
internal class DefaultPromptProvider : PromptProvider {
override fun getPrompt(): AttributedString
}Import:
import com.embabel.agent.shell.DefaultPromptProviderPrompt: "embabel> " (in yellow)
Visibility: Internal class, automatically used when no other prompt provider is configured
Usage: This provider is automatically registered by ShellConfiguration when no other PromptProvider bean is defined. You don't need to instantiate it directly.
Message generators provide dynamic content for prompt providers. They implement a simple interface for generating messages that are displayed alongside the prompt.
interface MessageGenerator {
fun generate(): String
}The MessageGenerator interface defines a single method that returns a string message. This message is typically displayed above or alongside the command prompt to add personality and context to the shell experience.
class RandomFromFileMessageGenerator(
private val url: String
) : MessageGenerator {
override fun generate(): String
}Import:
import com.embabel.common.util.RandomFromFileMessageGeneratorConstructor Parameters:
url: Path to a classpath resource file containing messages (one per line)Behavior:
generate()Resource Location: The url parameter refers to a classpath resource path, not a file system path. For example, "logging/starwars.txt" refers to a file in the src/main/resources/logging/starwars.txt directory of the application.
Usage:
import com.embabel.common.util.RandomFromFileMessageGenerator
val messageGenerator = RandomFromFileMessageGenerator(
url = "my-messages.txt"
)
val randomMessage = messageGenerator.generate()
println(randomMessage) // Prints a random message from the fileOpen base class for prompt providers that use dynamic message generation.
open class MessageGeneratorPromptProvider(
private val prompt: String,
private val color: Int,
private val messageGenerator: MessageGenerator
) : PromptProvider {
override fun getPrompt(): AttributedString
}Import:
import com.embabel.agent.shell.MessageGeneratorPromptProviderConstructor Parameters:
prompt: The prompt text to display (e.g., "starwars", "pythons")color: ANSI color code as an integermessageGenerator: MessageGenerator implementation for generating dynamic messagesBehavior:
Usage: Extend this class to create custom prompt providers:
import com.embabel.agent.shell.MessageGeneratorPromptProvider
import com.embabel.common.util.RandomFromFileMessageGenerator
import org.springframework.stereotype.Component
@Component
class MyPromptProvider : MessageGeneratorPromptProvider(
prompt = "my-app",
color = 0x00FF00, // Green
messageGenerator = RandomFromFileMessageGenerator(
url = "my-messages.txt"
)
)All personality providers extend MessageGeneratorPromptProvider and are conditionally loaded based on the embabel.agent.logging.personality configuration property.
@Component
@ConditionalOnProperty(name = ["embabel.agent.logging.personality"], havingValue = "starwars")
class StarWarsPromptProvider : MessageGeneratorPromptProvider(
color = StarWarsColorPalette.YELLOW_ACCENT,
prompt = "starwars",
messageGenerator = RandomFromFileMessageGenerator(
url = "logging/starwars.txt"
)
)Import:
import com.embabel.agent.shell.personality.starwars.StarWarsPromptProviderConfiguration:
embabel:
agent:
logging:
personality: starwarsPrompt: "starwars> " (in Star Wars yellow accent color)
Message Source: logging/starwars.txt
Color: StarWarsColorPalette.YELLOW_ACCENT (0xFFD700)
Usage: Automatically activated when personality is set to "starwars" in configuration. No manual instantiation needed.
@Component
@ConditionalOnProperty(name = ["embabel.agent.logging.personality"], havingValue = "severance")
class SeverancePromptProvider : MessageGeneratorPromptProvider(
color = LumonColorPalette.MEMBRANE,
prompt = LumonDepartments.random(),
messageGenerator = RandomFromFileMessageGenerator(
url = "logging/severance.txt"
)
)Import:
import com.embabel.agent.shell.personality.severance.SeverancePromptProviderConfiguration:
embabel:
agent:
logging:
personality: severancePrompt: Random Lumon department name (in Lumon membrane color)
Message Source: logging/severance.txt
Color: LumonColorPalette.MEMBRANE (0x87CEEB)
Module-level Constants:
val LumonDepartments: List<String>Contains list of Lumon department names:
@Component
@ConditionalOnProperty(name = ["embabel.agent.logging.personality"], havingValue = "hitchhiker")
class HitchhikerPromptProvider : MessageGeneratorPromptProvider(
color = HitchhikerColorPalette.BABEL_GREEN,
prompt = GuideEntries.random(),
messageGenerator = RandomFromFileMessageGenerator(
url = "logging/hitchhiker.txt"
)
)Import:
import com.embabel.agent.shell.personality.hitchhiker.HitchhikerPromptProviderConfiguration:
embabel:
agent:
logging:
personality: hitchhikerPrompt: Random Guide entry (in babel green color)
Message Source: logging/hitchhiker.txt
Color: HitchhikerColorPalette.BABEL_GREEN (0x32CD32)
Module-level Constants:
val GuideEntries: List<String>Contains list of Hitchhiker's Guide references:
@Component
@ConditionalOnProperty(name = ["embabel.agent.logging.personality"], havingValue = "colossus")
class ColossusPromptProvider : MessageGeneratorPromptProvider(
color = ColossusColorPalette.PANEL,
prompt = "Colossus",
messageGenerator = RandomFromFileMessageGenerator(
url = "logging/colossus.txt"
)
)Import:
import com.embabel.agent.shell.personality.colossus.ColossusPromptProviderConfiguration:
embabel:
agent:
logging:
personality: colossusPrompt: "Colossus> " (in Colossus panel color)
Message Source: logging/colossus.txt
Color: ColossusColorPalette.PANEL (0xFF4500)
@Component
@ConditionalOnProperty(name = ["embabel.agent.logging.personality"], havingValue = "montypython")
class MontyPythonPromptProvider : MessageGeneratorPromptProvider(
color = MontyPythonColorPalette.BRIGHT_RED,
prompt = "pythons",
messageGenerator = RandomFromFileMessageGenerator(
url = "logging/montypython.txt"
)
)Import:
import com.embabel.agent.shell.personality.montypython.MontyPythonPromptProviderConfiguration:
embabel:
agent:
logging:
personality: montypythonPrompt: "pythons> " (in Monty Python bright red color)
Message Source: logging/montypython.txt
Color: MontyPythonColorPalette.BRIGHT_RED (0xFF0000)
Each personality provider uses a specific color from its associated color palette. The following are the actual RGB integer values used:
0xFFD700 (Gold yellow, reminiscent of the Star Wars logo and C-3PO)0x87CEEB (Sky blue, representing the sterile corporate environment of Lumon Industries)0x32CD32 (Lime green, evoking the Babel Fish and the Guide's digital display)0xFF4500 (Orange-red, representing the computer panels and warning systems)0xFF0000 (Pure red, fitting the bold and absurd nature of Monty Python)These color values are passed to the MessageGeneratorPromptProvider constructor and are used to style the terminal prompt text via JLine's AttributedStyle.foreground() method.
To create a custom prompt provider:
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.shell.jline.PromptProvider
import org.jline.utils.AttributedString
import org.jline.utils.AttributedStyle
@Configuration
class CustomPromptConfiguration {
@Bean
fun customPromptProvider(): PromptProvider {
return PromptProvider {
AttributedString(
"custom> ",
AttributedStyle.DEFAULT.foreground(AttributedStyle.MAGENTA)
)
}
}
}import com.embabel.agent.shell.MessageGeneratorPromptProvider
import com.embabel.common.util.RandomFromFileMessageGenerator
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.stereotype.Component
@Component
@ConditionalOnProperty(name = ["embabel.agent.logging.personality"], havingValue = "custom")
class CustomPromptProvider : MessageGeneratorPromptProvider(
prompt = "custom",
color = 0xFF00FF, // Magenta
messageGenerator = RandomFromFileMessageGenerator(
url = "logging/custom.txt"
)
)Then configure:
embabel:
agent:
logging:
personality: customThe prompt provider is selected using Spring's conditional bean registration:
Only one prompt provider is active at a time.
tessl i tessl/maven-com-embabel-agent--embabel-agent-shell@0.3.0