Initial commit: add .gitignore and README
This commit is contained in:
93
fusionagi/schemas/commands.py
Normal file
93
fusionagi/schemas/commands.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""Interaction commands and user intent for Dvādaśa UX."""
|
||||
|
||||
import re
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from fusionagi.schemas.head import HeadId
|
||||
|
||||
|
||||
class UserIntent(str, Enum):
|
||||
"""User intent derived from commands or natural input."""
|
||||
|
||||
NORMAL = "normal"
|
||||
HEAD_STRATEGY = "head_strategy"
|
||||
SHOW_DISSENT = "show_dissent"
|
||||
RERUN_RISK = "rerun_risk"
|
||||
EXPLAIN_REASONING = "explain_reasoning"
|
||||
SOURCES = "sources"
|
||||
|
||||
|
||||
# Command patterns: /command [arg] or /command \n prompt
|
||||
_COMMAND_PATTERNS: list[tuple[re.Pattern[str], UserIntent]] = [
|
||||
(re.compile(r"^/head\s+(\w+)(?:\s+(.+))?\s*$", re.I | re.DOTALL), UserIntent.HEAD_STRATEGY),
|
||||
(re.compile(r"^/show\s+dissent(?:\s+(.+))?\s*$", re.I | re.DOTALL), UserIntent.SHOW_DISSENT),
|
||||
(re.compile(r"^/rerun\s+risk(?:\s+(.+))?\s*$", re.I | re.DOTALL), UserIntent.RERUN_RISK),
|
||||
(re.compile(r"^/explain\s+reasoning(?:\s+(.+))?\s*$", re.I | re.DOTALL), UserIntent.EXPLAIN_REASONING),
|
||||
(re.compile(r"^/sources(?:\s+(.+))?\s*$", re.I | re.DOTALL), UserIntent.SOURCES),
|
||||
]
|
||||
|
||||
|
||||
class ParsedCommand(BaseModel):
|
||||
"""Parsed user command with intent and optional arguments."""
|
||||
|
||||
intent: UserIntent = Field(..., description="Detected intent")
|
||||
head_id: HeadId | None = Field(default=None, description="For HEAD_STRATEGY: which head")
|
||||
raw_input: str = Field(default="", description="Original user input")
|
||||
cleaned_prompt: str = Field(default="", description="Prompt with command stripped if applicable")
|
||||
|
||||
|
||||
def parse_user_input(text: str) -> ParsedCommand:
|
||||
"""
|
||||
Parse user input to detect commands and extract intent.
|
||||
|
||||
Examples:
|
||||
"/head strategy" -> HEAD_STRATEGY, head_id=STRATEGY
|
||||
"/show dissent" -> SHOW_DISSENT
|
||||
"What is X?" -> NORMAL, cleaned_prompt="What is X?"
|
||||
"""
|
||||
stripped = (text or "").strip()
|
||||
if not stripped:
|
||||
return ParsedCommand(
|
||||
intent=UserIntent.NORMAL,
|
||||
raw_input=stripped,
|
||||
cleaned_prompt=stripped,
|
||||
)
|
||||
|
||||
for pattern, intent in _COMMAND_PATTERNS:
|
||||
match = pattern.match(stripped)
|
||||
if match:
|
||||
head_id = None
|
||||
cleaned = ""
|
||||
if intent == UserIntent.HEAD_STRATEGY:
|
||||
arg = (match.group(1) or "").lower()
|
||||
rest = match.group(2) if match.lastindex and match.lastindex >= 2 else None
|
||||
cleaned = (rest or "").strip()
|
||||
try:
|
||||
head_id = HeadId(arg)
|
||||
except ValueError:
|
||||
head_id = None
|
||||
else:
|
||||
rest = match.group(1) if match.lastindex and match.lastindex >= 1 else None
|
||||
cleaned = (rest or "").strip()
|
||||
return ParsedCommand(
|
||||
intent=intent,
|
||||
head_id=head_id,
|
||||
raw_input=stripped,
|
||||
cleaned_prompt=cleaned,
|
||||
)
|
||||
|
||||
return ParsedCommand(
|
||||
intent=UserIntent.NORMAL,
|
||||
raw_input=stripped,
|
||||
cleaned_prompt=stripped,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"UserIntent",
|
||||
"ParsedCommand",
|
||||
"parse_user_input",
|
||||
]
|
||||
Reference in New Issue
Block a user