"""
Type Definitions for Centralized Slash Command System
This module provides the foundational type definitions for the Osprey Framework's
unified slash command system. The type system enables type-safe command registration,
execution, and context management across all framework interfaces.
Architecture:
- CommandCategory: Hierarchical command organization for discovery and validation
- CommandResult: Standardized execution outcomes for interface coordination
- CommandContext: Rich execution context with interface-specific data
- Command: Complete command specification with metadata and handlers
- CommandHandler: Protocol for type-safe command implementation
The type system supports extensible command categories, context-aware execution,
and seamless integration with CLI, OpenWebUI, and custom interfaces through
a unified command registry and execution model.
"""
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Protocol
[docs]
class CommandCategory(Enum):
"""Categories of slash commands for organization and interface validation.
Command categories provide hierarchical organization and enable interface-specific
command filtering. Each category represents a distinct functional domain with
specific execution contexts and validation requirements.
Categories:
CLI: Interface and user experience commands (help, clear, exit, history)
AGENT_CONTROL: Agent behavior and execution control (planning, approval, debug)
SERVICE: Framework service management (status, logs, metrics, restart)
CUSTOM: Application-specific and user-defined extensions
.. note::
Categories are used for command discovery, autocompletion filtering,
and interface-specific command availability validation.
"""
CLI = "cli" # Interface/UI commands (help, clear, exit)
AGENT_CONTROL = "agent" # Agent behavior control (planning, approval, debug)
SERVICE = "service" # Service-specific commands (logs, metrics)
CUSTOM = "custom" # User-defined custom commands
[docs]
class CommandResult(Enum):
"""Standardized result types for command execution flow control.
Command results enable interfaces to coordinate execution flow and handle
different command outcomes appropriately. Results provide clear semantics
for command processing continuation, state changes, and interface control.
Results:
CONTINUE: Command processed, continue with normal message flow
HANDLED: Command fully processed, stop further message processing
EXIT: Request interface termination (CLI exit, session end)
AGENT_STATE_CHANGED: Agent control state modified, may affect execution
.. note::
Interfaces should handle each result type appropriately based on their
execution model and user experience requirements.
"""
CONTINUE = "continue" # Continue normal processing
HANDLED = "handled" # Command was handled, stop processing
EXIT = "exit" # Exit the current interface
AGENT_STATE_CHANGED = "agent_state_changed" # Agent control state was modified
[docs]
@dataclass
class CommandContext:
"""Execution context information available to command handlers.
CommandContext provides rich contextual information to command handlers,
enabling context-aware command execution with access to interface state,
agent configuration, and service instances. The context supports multiple
interface types while maintaining type safety and extensibility.
Context Categories:
Interface Context: Interface type, user identification, session management
CLI Context: CLI instance access, console output, terminal control
Agent Context: Current agent state, gateway access, configuration
Service Context: Service instance access, deployment information
Extension Context: Custom context data for application-specific commands
:param interface_type: Interface identifier ("cli", "openwebui", "api", etc.)
:type interface_type: str
:param user_id: User identifier for multi-user interfaces
:type user_id: Optional[str]
:param session_id: Session identifier for state management
:type session_id: Optional[str]
:param cli_instance: CLI interface instance for direct access
:type cli_instance: Optional[Any]
:param console: Rich console instance for formatted output
:type console: Optional[Any]
:param agent_state: Current agent state for state-aware commands
:type agent_state: Optional[Dict[str, Any]]
:param gateway: Gateway instance for message processing
:type gateway: Optional[Any]
:param config: Framework configuration for service access
:type config: Optional[Dict[str, Any]]
:param service_instance: Service instance for service-specific commands
:type service_instance: Optional[Any]
:param extra: Additional context data for custom extensions
:type extra: Dict[str, Any]
.. note::
Context fields are populated based on the executing interface and
command category. Not all fields are available in all contexts.
Examples:
CLI command context::
context = CommandContext(
interface_type="cli",
cli_instance=cli,
console=rich_console,
agent_state=current_state
)
Service command context::
context = CommandContext(
interface_type="api",
service_instance=jupyter_service,
config=framework_config
)
"""
# Interface context
interface_type: str = "unknown" # "cli", "openwebui", "api", etc.
user_id: str | None = None
session_id: str | None = None
# CLI-specific context
cli_instance: Any | None = None
console: Any | None = None
# Agent context
agent_state: dict[str, Any] | None = None
gateway: Any | None = None
config: dict[str, Any] | None = None
# Service context
service_instance: Any | None = None
# Additional context data
extra: dict[str, Any] = field(default_factory=dict)
class CommandHandler(Protocol):
"""Protocol for type-safe command handler function signatures.
CommandHandler defines the interface contract for all command handler
functions, ensuring consistent signatures and return types across
the command system. Handlers receive parsed arguments and execution
context, returning standardized results or state changes.
Handler Contract:
- Accept string arguments and CommandContext
- Return CommandResult or Dict[str, Any] for state changes
- Handle errors gracefully with appropriate user feedback
- Support both synchronous and asynchronous execution
.. note::
Agent control commands may return dictionaries representing
state changes instead of CommandResult values.
"""
async def __call__(self, args: str, context: CommandContext) -> CommandResult | dict[str, Any]:
"""Execute the command.
Args:
args: Command arguments as string
context: Execution context
Returns:
CommandResult or dict of state changes for agent control commands
"""
...
[docs]
@dataclass
class Command:
"""Complete specification for a slash command with metadata and execution constraints.
The Command class provides a comprehensive definition for slash commands in the
Osprey Framework. It includes execution handlers, validation constraints,
interface restrictions, and rich metadata for help generation and autocompletion.
Command Lifecycle:
1. **Definition**: Command created with required fields and optional metadata
2. **Registration**: Command registered in CommandRegistry with validation
3. **Discovery**: Command discovered through registry lookup and filtering
4. **Execution**: Command executed with context and argument validation
5. **Completion**: Command provides autocompletion suggestions
**Core Components:**
- **Required Fields**: name, category, description, handler for basic functionality
- **Metadata**: aliases, help_text, syntax for user experience and documentation
- **Constraints**: requires_args, valid_options, interface_restrictions for validation
- **Display**: hidden, deprecated flags for command visibility and lifecycle
:param name: Unique command identifier used for registration and execution
:type name: str
:param category: Command category for organization and filtering
:type category: CommandCategory
:param description: Brief description for help text and documentation
:type description: str
:param handler: Function or callable that executes the command logic
:type handler: CommandHandler
:param aliases: Alternative names for the command (shortcuts, compatibility)
:type aliases: List[str]
:param help_text: Detailed help text with usage examples and options
:type help_text: Optional[str]
:param syntax: Command syntax pattern for help display and validation
:type syntax: Optional[str]
:param requires_args: Whether the command requires arguments to execute
:type requires_args: bool
:param valid_options: List of valid argument values for validation
:type valid_options: Optional[List[str]]
:param interface_restrictions: List of interfaces where command is available
:type interface_restrictions: Optional[List[str]]
:param hidden: Whether command is hidden from help and autocompletion
:type hidden: bool
:param deprecated: Whether command is deprecated (shown with warning)
:type deprecated: bool
Examples:
Simple command definition::
command = Command(
name="status",
category=CommandCategory.SERVICE,
description="Show service status",
handler=status_handler
)
Command with validation and help::
command = Command(
name="planning",
category=CommandCategory.AGENT_CONTROL,
description="Control planning mode",
handler=planning_handler,
aliases=["plan"],
valid_options=["on", "off", "enabled", "disabled"],
help_text="Enable or disable planning mode.\\n\\nOptions:\\n on/enabled - Enable planning\\n off/disabled - Disable planning",
interface_restrictions=["cli", "openwebui"]
)
Hidden administrative command::
command = Command(
name="internal_debug",
category=CommandCategory.CUSTOM,
description="Internal debugging command",
handler=debug_handler,
hidden=True,
requires_args=True
)
"""
name: str
category: CommandCategory
description: str
handler: CommandHandler
# Command metadata
aliases: list[str] = field(default_factory=list)
help_text: str | None = None
syntax: str | None = None
# Execution constraints
requires_args: bool = False
valid_options: list[str] | None = None
interface_restrictions: list[str] | None = None # ["cli", "openwebui"]
# Gateway routing - when True, command MUST go through Gateway for processing
# This ensures consistent behavior across all interfaces (CLI, OpenWebUI, API)
# Examples: /chat, /exit (in direct chat), /planning - these affect agent state
# Commands with gateway_handled=False are interface-specific (/help, /clear)
gateway_handled: bool = False
# Display properties
hidden: bool = False
deprecated: bool = False
[docs]
def __post_init__(self):
"""Initialize computed fields and auto-generate missing metadata.
Automatically generates help_text from description if not provided,
and creates syntax patterns based on valid_options and requires_args
settings for consistent command documentation and validation.
"""
if self.help_text is None:
self.help_text = self.description
if self.syntax is None:
if self.valid_options:
options = "|".join(self.valid_options)
self.syntax = (
f"/{self.name}:{options}" if self.requires_args else f"/{self.name}[:{options}]"
)
else:
self.syntax = f"/{self.name}:<value>" if self.requires_args else f"/{self.name}"
[docs]
def is_valid_for_interface(self, interface_type: str) -> bool:
"""Check if command is valid for the given interface type.
Validates whether the command can be executed in the specified interface
based on interface_restrictions. Commands without restrictions are
available in all interfaces.
:param interface_type: Interface identifier ("cli", "openwebui", "api", etc.)
:type interface_type: str
:return: True if command is available in the interface, False otherwise
:rtype: bool
Examples:
Check CLI availability::
if command.is_valid_for_interface("cli"):
# Command can be used in CLI
pass
"""
if self.interface_restrictions is None:
return True
return interface_type in self.interface_restrictions
[docs]
def validate_option(self, option: str | None) -> bool:
"""Validate command arguments against defined constraints.
Performs validation of command arguments based on requires_args and
valid_options settings. Used by the command registry to ensure
proper command usage before execution.
:param option: Command argument to validate (None if no argument provided)
:type option: Optional[str]
:return: True if argument is valid, False if validation fails
:rtype: bool
Validation Rules:
- If requires_args=True, option cannot be None
- If valid_options is set, option must be in the list
- If no constraints, any option (including None) is valid
Examples:
Validate planning command::
# Command with valid_options=["on", "off"]
command.validate_option("on") # True
command.validate_option("invalid") # False
command.validate_option(None) # True (optional)
"""
if self.requires_args and option is None:
return False
if self.valid_options and option is not None:
return option in self.valid_options
return True
@dataclass
class ParsedCommand:
"""Result of parsing a command line."""
command_name: str
option: str | None = None
remaining_text: str = ""
is_valid: bool = True
error_message: str | None = None
class CommandExecutionError(Exception):
"""Exception raised during command execution."""
def __init__(self, message: str, command_name: str, suggestion: str | None = None):
super().__init__(message)
self.command_name = command_name
self.suggestion = suggestion