diff --git a/README.md b/README.md index 2aed5b7..5406d7a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,21 @@ # EnzoBot -EnzoBot A Virtual Freind ready to assist you with any tasks you need + +EnzoBot is a lightweight assistant with a structured response style and a simple CLI. + +## Features + +- Intent-aware responses for greetings, planning, and coding prompts +- Structured markdown-style output with clear headings +- Deterministic behavior suitable for local testing + +## Run + +```bash +python3 src/enzobot.py +``` + +## Test + +```bash +python3 -m pytest -q +``` diff --git a/src/enzobot.py b/src/enzobot.py new file mode 100644 index 0000000..6bff4f2 --- /dev/null +++ b/src/enzobot.py @@ -0,0 +1,110 @@ +from __future__ import annotations + +from dataclasses import dataclass +import re +from typing import Callable + + +@dataclass(frozen=True) +class IntentRule: + """Maps keyword patterns to an intent handler.""" + + name: str + pattern: re.Pattern[str] + handler: Callable[[str], str] + + +class EnzoBot: + """A lightweight, deterministic assistant for local use.""" + + def __init__(self) -> None: + self.rules = ( + IntentRule("greeting", re.compile(r"\b(hi|hello|hey)\b", re.I), self._handle_greeting), + IntentRule("plan", re.compile(r"\b(plan|roadmap|strategy)\b", re.I), self._handle_plan), + IntentRule("code", re.compile(r"\b(code|python|bug|refactor|test)\b", re.I), self._handle_code), + ) + + def respond(self, prompt: str) -> str: + """Return a premium-style, structured response for the user prompt.""" + clean_prompt = prompt.strip() + if not clean_prompt: + return self._empty_prompt_response() + + for rule in self.rules: + if rule.pattern.search(clean_prompt): + return rule.handler(clean_prompt) + + return self._handle_general(clean_prompt) + + def _empty_prompt_response(self) -> str: + return ( + "## Quick Start\n" + "- Share your goal in one sentence.\n" + "- Add constraints (time, tools, budget).\n" + "- I will return ranked options with next steps." + ) + + def _handle_greeting(self, _: str) -> str: + return ( + "## Hello 👋\n" + "I can help with strategy, coding, and execution planning.\n\n" + "### Fast Paths\n" + "- **Build something:** describe the feature and stack.\n" + "- **Fix an issue:** share error + expected behavior.\n" + "- **Plan work:** share objective + deadline." + ) + + def _handle_plan(self, prompt: str) -> str: + return ( + "## Strategic Plan\n" + f"**Objective:** {prompt}\n\n" + "### Recommended Sequence\n" + "1. Define measurable outcome (what success looks like).\n" + "2. Break into milestones with owners and deadlines.\n" + "3. Track risks weekly and adjust scope early.\n\n" + "### Optimization\n" + "- Prioritize high-impact, low-effort tasks first." + ) + + def _handle_code(self, prompt: str) -> str: + return ( + "## Engineering Response\n" + f"**Request:** {prompt}\n\n" + "### Ranked Approach\n" + "1. Reproduce the issue with a minimal test case.\n" + "2. Implement the smallest safe fix.\n" + "3. Add tests for regression prevention.\n" + "4. Refactor only after tests pass.\n\n" + "### Deliverables\n" + "- Patch diff\n" + "- Test evidence\n" + "- Follow-up hardening ideas" + ) + + def _handle_general(self, prompt: str) -> str: + return ( + "## Solution Framework\n" + f"**Input:** {prompt}\n\n" + "### Option Ranking\n" + "1. **Direct path:** fastest to execution.\n" + "2. **Balanced path:** speed + robustness.\n" + "3. **High-upside path:** innovation-focused.\n\n" + "### Next Action\n" + "- Reply with constraints and I will produce an implementation plan." + ) + + +def main() -> None: + bot = EnzoBot() + print("EnzoBot CLI ready. Type 'exit' to quit.") + while True: + user_input = input("You> ").strip() + if user_input.lower() in {"exit", "quit"}: + print("EnzoBot> Goodbye.") + break + print("EnzoBot>") + print(bot.respond(user_input)) + + +if __name__ == "__main__": + main() diff --git a/tests/test_enzobot.py b/tests/test_enzobot.py new file mode 100644 index 0000000..c375ace --- /dev/null +++ b/tests/test_enzobot.py @@ -0,0 +1,20 @@ +from src.enzobot import EnzoBot + + +def test_empty_prompt_returns_quick_start() -> None: + bot = EnzoBot() + response = bot.respond(" ") + assert "## Quick Start" in response + + +def test_code_prompt_uses_engineering_response() -> None: + bot = EnzoBot() + response = bot.respond("Help me debug this Python bug") + assert "## Engineering Response" in response + assert "Ranked Approach" in response + + +def test_general_prompt_returns_framework() -> None: + bot = EnzoBot() + response = bot.respond("I want to improve team communication") + assert "## Solution Framework" in response