diff --git a/.agents/skills/README.md b/.agents/skills/README.md new file mode 100644 index 0000000..73942ac --- /dev/null +++ b/.agents/skills/README.md @@ -0,0 +1,341 @@ +# Mind-Bus Skills Documentation + +## Overview + +This directory contains **reusable development skills** for the Mind-Bus AI Agent platform. These skills encapsulate domain knowledge, design patterns, and best practices to accelerate development across all modules. + +## 📚 Skills Directory + +```bash +.agents/skills/ +├── mindbus-skill/ # Master expert skill for Mind-Bus +├── agent-orchestration/ # LangGraph node and graph patterns +├── memory-system/ # Memory extraction, storage, retrieval +├── rag-retrieval/ # RAG/CAG retrieval and semantic search +├── backend-api/ # FastAPI routes, services, schemas +├── frontend-components/ # Vue 3 components, stores, routing +├── SKILLS-INDEX.md # Central index and workflow guide +└── README.md # This file +``` + +## 🚀 Quick Start + +### For Agent Development + +Use the **agent-orchestration** skill when: + +- Building new LangGraph nodes +- Designing agent control flows +- Implementing tool execution +- Managing conversation state + +### For Memory Features + +Use the **memory-system** skill when: + +- Extracting memories from conversations +- Storing episodic/semantic/correction memories +- Retrieving context for the agent +- Implementing memory scoring + +### For Retrieval Systems + +Use the **rag-retrieval** skill when: + +- Implementing semantic search +- Building hybrid RAG+CAG retrieval +- Chunking and storing documents +- Ranking search results + +### For API Development + +Use the **backend-api** skill when: + +- Creating FastAPI endpoints +- Designing request/response schemas +- Implementing services and business logic +- Adding authentication and authorization + +### For Frontend Development + +Use the **frontend-components** skill when: + +- Building Vue 3 components +- Managing state with Pinia +- Adding routes and navigation +- Creating forms and handling user input + +## 📖 How to Use These Skills + +### Option 1: In Chat + +Type `/mindbus-expert` or any specific skill name in GitHub Copilot Chat to invoke the skill with its full knowledge base. + +### Option 2: Direct Reference + +Open the relevant `SKILL.md` file in the skill directory for quick pattern lookups. + +### Option 3: Guided Navigation + +Start with `SKILLS-INDEX.md` to: + +- Understand which skill to use +- See the development workflow +- Find related skills +- Check quick references + +## 🎯 Typical Development Workflows + +### Building a Complete Feature (End-to-End) + +```bash +1. Plan with agent-orchestration + ↓ +2. Implement with backend-api + ↓ +3. Add retrieval with rag-retrieval (if needed) + ↓ +4. Use memory-system (if using memories) + ↓ +5. Build UI with frontend-components +``` + +### Adding Memory to Agent + +```bash +1. memory-system: Design memory types + ↓ +2. agent-orchestration: Add extraction node + ↓ +3. memory-system: Implement storage + ↓ +4. rag-retrieval: Integrate retrieval + ↓ +5. frontend-components: Build UI +``` + +### Implementing RAG Search + +```bash +1. rag-retrieval: Plan retrieval strategy + ↓ +2. backend-api: Create search endpoint + ↓ +3. frontend-components: Build search UI +``` + +## 📝 Skill File Structure + +Each skill contains: + +```markdown +--- +name: skill-name +description: "Use when: specific use cases" +keywords: [list, of, keywords] +--- + +# Skill Title + +## Quick Start +- Basic examples and setup + +## Core Patterns +- Implementation patterns +- Common approaches + +## Examples +- Concrete code examples +- Copy-paste ready + +## Testing +- Testing patterns +- Test examples + +## Common Mistakes +- What to avoid +- Best practices + +## References +- Links to related code +- Documentation +``` + +## 🔗 Key Integration Points + +### Agent System (`agent/`) + +- **agent-orchestration** - Node design and graph flows +- **memory-system** - Memory extraction in nodes +- **rag-retrieval** - Retrieval nodes + +### Memory System (`memory/`) + +- **memory-system** - All memory operations +- **backend-api** - Memory endpoints +- **frontend-components** - Memory UI + +### Retrieval System (`agent/retrieval/`) + +- **rag-retrieval** - Core retrieval patterns +- **agent-orchestration** - Retrieval nodes +- **backend-api** - Search endpoints + +### API (`apps/api/`) + +- **backend-api** - All API patterns +- **agent-orchestration** - Agent endpoints +- **memory-system** - Memory endpoints +- **rag-retrieval** - Search endpoints + +### Frontend (`frontend/`) + +- **frontend-components** - All UI patterns +- **backend-api** - API service integration + +## 💡 When to Create New Skills + +Create a new skill when: + +- ✅ A significant module or feature area needs documentation +- ✅ Multiple developers work on the same area +- ✅ Complex patterns emerge across multiple files +- ✅ The knowledge is reusable across projects + +Don't create new skills when: + +- ❌ It's a one-time or very specific implementation +- ❌ It's already well-documented in code comments +- ❌ It belongs in an existing skill + +## 🔍 Finding the Right Skill + +Use this decision tree: + +```bash +I'm working on... + +├─ Agent nodes or flows? → agent-orchestration +├─ Memory extraction/storage? → memory-system +├─ Semantic search or RAG? → rag-retrieval +├─ API endpoints/services? → backend-api +├─ Vue components/stores? → frontend-components +├─ General architecture? → mindbus-expert +└─ Not sure? → Start with SKILLS-INDEX.md +``` + +## 📚 Cross-Skill References + +### agent-orchestration + +- Uses: **memory-system** (in retriever nodes) +- Uses: **rag-retrieval** (in retriever nodes) +- Used by: **backend-api** (agent endpoints) +- Used by: **frontend-components** (chat UI) + +### memory-system + +- Uses: **rag-retrieval** (vector storage) +- Used by: **agent-orchestration** (memory nodes) +- Used by: **backend-api** (memory endpoints) +- Used by: **frontend-components** (memory UI) + +### rag-retrieval + +- Uses: **memory-system** (memory vector storage) +- Used by: **agent-orchestration** (retriever nodes) +- Used by: **backend-api** (search endpoints) +- Used by: **frontend-components** (search UI) + +### backend-api + +- Uses: **agent-orchestration** (agent endpoints) +- Uses: **memory-system** (memory endpoints) +- Uses: **rag-retrieval** (search endpoints) +- Used by: **frontend-components** (API calls) + +### frontend-components + +- Uses: **backend-api** (API integration) +- Used by: **mindbus-expert** (overview) + +## 🛠️ Maintaining These Skills + +When updating Mind-Bus code: + +1. **If you change patterns**: Update the relevant skill +2. **If you add a new module**: Consider creating a skill +3. **If you find a bug in a pattern**: Fix it in the skill +4. **If patterns change**: Update all cross-references + +### Updating a Skill + +1. Edit the `SKILL.md` file +2. Update patterns, examples, and references +3. Test examples are still valid +4. Update cross-references in other skills +5. Update `SKILLS-INDEX.md` if needed + +## 📖 Learning Path for New Developers + +### Week 1: Foundations + +1. Read `mindbus-expert` for overview +2. Read `SKILLS-INDEX.md` for architecture +3. Run `docker-compose up` locally + +### Week 2: Core Modules + +1. **agent-orchestration** - Understand agent flows +2. **memory-system** - Understand memory architecture +3. **rag-retrieval** - Understand retrieval patterns + +### Week 3: Implementation + +1. **backend-api** - Build simple endpoint +2. **frontend-components** - Build simple component +3. Work on a small task using multiple skills + +### Week 4+: Deep Work + +- Pick a module and become expert +- Contribute to improvements +- Update skills with learnings + +## 🤝 Contributing Improvements + +Found better patterns? Want to document edge cases? + +1. Create a PR with skill improvements +2. Reference the relevant code +3. Include concrete examples +4. Test examples before submitting +5. Update related skills if needed + +## 📞 Getting Help + +- **Stuck on agent logic?** Check `agent-orchestration` +- **Memory questions?** Check `memory-system` +- **Search problems?** Check `rag-retrieval` +- **API issues?** Check `backend-api` +- **UI problems?** Check `frontend-components` +- **Architecture questions?** Check `mindbus-expert` or `SKILLS-INDEX.md` + +## 🎓 Related Documentation + +- **Code**: See inline comments in relevant modules +- **Tests**: See `tests/` directory for patterns +- **Docs**: See `docs/` directory for detailed guides +- **Examples**: See example files and patterns in each module + +## Version Info + +- **Last Updated**: June 2026 +- **Mind-Bus Version**: Main branch +- **Python**: 3.10+ +- **Vue**: 3.x +- **FastAPI**: Latest + +## License + +These skills are part of the Mind-Bus project and follow the same license (check LICENSE file in repo root). diff --git a/.agents/skills/SKILLS-INDEX.md b/.agents/skills/SKILLS-INDEX.md new file mode 100644 index 0000000..08133b8 --- /dev/null +++ b/.agents/skills/SKILLS-INDEX.md @@ -0,0 +1,415 @@ +--- +name: "Mind-Bus Skills Hub" +description: "Central guide to all Mind-Bus development skills. Reference for agent orchestration, memory systems, retrieval, backend API, and frontend development." +--- + +# Mind-Bus Skills Hub + +Complete guide to reusable skills for the Mind-Bus persistent AI agent platform. + +## 📚 Available Skills + +### 1. **mindbus-expert** (Master Skill) + +**When to use**: General Mind-Bus development, architecture questions, feature planning + +**Covers**: + +- Project architecture overview +- Stack and technologies +- Module structure and roles +- Common development workflows +- Debugging and deployment tips + +**Key Topics**: + +- Backend: FastAPI, LangGraph, PostgreSQL, Qdrant, Redis +- Frontend: Vue 3, TypeScript, Pinia +- Infrastructure: Docker, deployment strategies +- Security and performance + +--- + +### 2. **agent-orchestration** + +**When to use**: Building LangGraph nodes, designing agent flows, managing state, routing logic + +**Covers**: + +- Node implementation patterns (retriever, planner, responder, tool runner, reflector) +- Graph design patterns (sequential, conditional, loops) +- State management and message history +- Error handling in async nodes +- Testing patterns for nodes + +**Key Code Locations**: + +- `agent/graph.py` - Graph orchestration +- `agent/nodes/` - Node implementations +- `agent/state/state.py` - AgentState definition +- `agent/langgraph_compat.py` - LangGraph compatibility + +**Example Use Cases**: + +- ✅ Add a new processing node +- ✅ Implement tool execution flow +- ✅ Create conditional routing between nodes +- ✅ Add reflection/feedback loop + +--- + +### 3. **memory-system** + +**When to use**: Working with episodic/semantic/correction memory, extracting memories, retrieval + +**Covers**: + +- Three memory types (episodic, semantic, correction) +- Memory extraction pipeline from conversations +- Storage in PostgreSQL and vector DB +- Short-term working memory patterns +- Semantic search and scoring +- Context building from memories + +**Key Code Locations**: + +- `memory/long_term.py` - LongTermMemoryManager +- `memory/short_term.py` - ShortTermMemory +- `memory/extraction.py` - Memory extraction +- `memory/schemas.py` - Memory models +- `memory/scoring.py` - Memory importance scoring +- `storage/postgres.py` - DB backend + +**Example Use Cases**: + +- ✅ Extract memories from user messages +- ✅ Store episodic/semantic/correction memories +- ✅ Retrieve relevant memories for context +- ✅ Implement memory scoring and filtering +- ✅ Build context from multiple memory types + +--- + +### 4. **rag-retrieval** + +**When to use**: Implementing RAG/CAG retrieval, semantic search, chunking, reranking + +**Covers**: + +- RAG (semantic vector search) vs CAG (cached retrieval) +- Hybrid search combining both approaches +- Document chunking strategies +- Vector database operations (Qdrant) +- Semantic search implementation +- Cache-based retrieval (Redis) +- Result reranking + +**Key Code Locations**: + +- `agent/retrieval/hybrid_search.py` - Hybrid search +- `agent/retrieval/qdrant_client.py` - Vector DB client +- `agent/retrieval/chunking.py` - Document segmentation +- `agent/retrieval/rerank.py` - Result ranking + +**Example Use Cases**: + +- ✅ Chunk documents for vector storage +- ✅ Implement semantic search +- ✅ Create cache-based retrieval +- ✅ Combine RAG + CAG for optimal results +- ✅ Rerank results by relevance +- ✅ Manage Qdrant collections + +--- + +### 5. **backend-api** + +**When to use**: Adding FastAPI routes, creating schemas, implementing services, authentication + +**Covers**: + +- Route and endpoint creation +- Pydantic schema definition +- Service layer patterns +- Dependency injection +- Error handling and validation +- Authentication and authorization (JWT) +- Pagination and filtering +- Middleware and logging +- Background tasks +- Testing patterns + +**Key Code Locations**: + +- `apps/api/main.py` - FastAPI app +- `apps/api/routes/` - Endpoint definitions +- `apps/api/services/` - Business logic +- `apps/api/schemas/` - Pydantic models +- `apps/api/security.py` - JWT handling +- `apps/api/middleware/` - Custom middleware + +**Example Use Cases**: + +- ✅ Create new API endpoint +- ✅ Add authentication to endpoint +- ✅ Implement pagination +- ✅ Add error handling +- ✅ Create service for business logic +- ✅ Queue background tasks +- ✅ Add request/response logging + +--- + +### 6. **frontend-components** + +**When to use**: Building Vue 3 components, Pinia stores, routes, forms, API integration + +**Covers**: + +- Vue 3 component structure (Composition API) +- Pinia store patterns and state management +- Router and navigation guards +- Form handling and validation +- API service integration with interceptors +- Component props, emits, and composition +- SCSS styling with Tailwind colors +- Testing patterns with Vitest +- Performance optimization + +**Key Code Locations**: + +- `frontend/src/views/` - Page components +- `frontend/src/components/` - Reusable components +- `frontend/src/stores/` - Pinia stores +- `frontend/src/services/api.ts` - API integration +- `frontend/src/router/index.ts` - Route config +- `frontend/src/style.scss` - Global styles + +**Example Use Cases**: + +- ✅ Create new Vue component +- ✅ Add Pinia store for state management +- ✅ Implement form with validation +- ✅ Add new route and navigation +- ✅ Integrate API calls with Pinia +- ✅ Create reusable component library +- ✅ Style with SCSS and Tailwind + +--- + +## 🔄 Development Workflows + +### Add a Chat Feature + +**Skill Order**: `agent-orchestration` → `memory-system` → `rag-retrieval` → `backend-api` → `frontend-components` + +1. Design agent flow in **agent-orchestration** +2. Extract and store memories in **memory-system** +3. Implement RAG retrieval in **rag-retrieval** +4. Create `/chat` endpoint in **backend-api** +5. Build ChatView component in **frontend-components** + +### Implement Memory Management + +**Skill Order**: `memory-system` → `backend-api` → `frontend-components` + +1. Define memory types in **memory-system** +2. Create memory endpoints in **backend-api** +3. Build memory UI in **frontend-components** + +### Add a Tool Integration + +**Skill Order**: `agent-orchestration` → `backend-api` + +1. Create tool node in **agent-orchestration** +2. Add tool endpoint in **backend-api** +3. Integrate with agent graph + +### Build API Feature + +**Skill Order**: `backend-api` → `frontend-components` + +1. Create endpoint in **backend-api** +2. Add store and component in **frontend-components** + +--- + +## 🎯 Quick Reference + +| Task | Primary Skill | Secondary Skills | +| ------ | --------------- | ------------------ | +| Add agent node | agent-orchestration | - | +| Implement memory extraction | memory-system | agent-orchestration | +| Build semantic search | rag-retrieval | memory-system | +| Create API endpoint | backend-api | agent-orchestration | +| Build UI component | frontend-components | backend-api | +| Full feature (end-to-end) | all | - | + +--- + +## 📂 Project Structure + +```bash +Mind-Bus/ +├── agent/ # LangGraph orchestration +│ ├── graph.py # Main graph (see: agent-orchestration) +│ ├── nodes/ # Processing nodes +│ ├── state/ # State definition +│ ├── retrieval/ # RAG/CAG (see: rag-retrieval) +│ └── policies/ # Agent behaviors +├── memory/ # Memory system (see: memory-system) +│ ├── long_term.py +│ ├── short_term.py +│ ├── extraction.py +│ └── schemas.py +├── apps/api/ # FastAPI (see: backend-api) +│ ├── main.py +│ ├── routes/ +│ ├── services/ +│ ├── schemas/ +│ └── security.py +├── frontend/ # Vue 3 (see: frontend-components) +│ ├── src/ +│ │ ├── views/ +│ │ ├── components/ +│ │ ├── stores/ +│ │ ├── services/ +│ │ └── router/ +│ └── vite.config.ts +├── storage/ # Database backends +├── observability/ # Logging and monitoring +├── deploy/ # Deployment configs +└── docker-compose.yml # Local development +``` + +--- + +## 🛠️ Common Patterns + +### State Management + +- Use immutable patterns (accumulate state changes) +- Return only changed fields from nodes/endpoints +- Always preserve message history + +### Error Handling + +- Async try/catch in all operations +- Log errors with context +- Return user-friendly error messages +- Include error details in response + +### Testing + +- Unit tests for individual components +- Integration tests for workflows +- Mock external dependencies +- Test both success and error paths + +### Performance + +- Batch operations where possible +- Use caching (Redis for frequent queries, short-term memory) +- Async/await throughout (no blocking) +- Connection pooling for databases + +--- + +## 🔗 Stack Technologies + +### Backend + +- **FastAPI** - Web framework +- **LangGraph** - Agent orchestration +- **PostgreSQL** - Relational database +- **Qdrant** - Vector database +- **Redis** - Caching and queuing +- **RQ** - Task queue +- **Pydantic** - Data validation + +### Frontend + +- **Vue 3** - UI framework +- **TypeScript** - Type safety +- **Pinia** - State management +- **Vite** - Build tool +- **Axios** - HTTP client +- **Vue Router** - Routing + +### Infrastructure + +- **Docker** - Containerization +- **PostgreSQL** - Main database +- **Qdrant** - Vector DB +- **Redis** - Cache/queue + +--- + +## 📖 Documentation + +- **FastAPI**: +- **Vue 3**: +- **LangGraph**: +- **Pinia**: +- **Qdrant**: +- **PostgreSQL**: + +--- + +## 🚀 Getting Started + +1. **New to Mind-Bus?** Start with `mindbus-expert` for overview +2. **Working on agent logic?** Use `agent-orchestration` + `memory-system` +3. **Building features?** Use `backend-api` + `frontend-components` +4. **Optimizing retrieval?** Use `rag-retrieval` + +--- + +## 💡 Best Practices + +✅ **Do**: + +- Use Pydantic for all API schemas +- Always validate input +- Write tests alongside code +- Use async/await consistently +- Document complex logic +- Preserve message history +- Filter by user_id in queries + +❌ **Don't**: + +- Use blocking operations in async code +- Skip input validation +- Store every message as memory +- Ignore confidence scores +- Log sensitive data +- Query all data without filtering + +--- + +## 🤝 Contributing Skills + +When adding new skills: + +1. Create skill directory in `.agents/skills//` +2. Create `SKILL.md` with YAML frontmatter and content +3. Include: + - Clear description and keywords + - Quick start examples + - Implementation patterns + - Testing patterns + - Common mistakes + - References to code locations + - Performance tips + +--- + +## 📞 Support + +For questions about: + +- **Architecture**: See `mindbus-expert` +- **Specific modules**: See relevant skill +- **Code patterns**: Check `SKILL.md` examples +- **Testing**: Check testing patterns in each skill diff --git a/.agents/skills/agent-orchestration/SKILL.md b/.agents/skills/agent-orchestration/SKILL.md new file mode 100644 index 0000000..d6c2b44 --- /dev/null +++ b/.agents/skills/agent-orchestration/SKILL.md @@ -0,0 +1,225 @@ +--- +name: agent-orchestration +description: "Use when: implementing LangGraph agent nodes, building control flows, managing conversation state, routing between nodes, handling tool execution, or designing agent graphs" +keywords: ["langgraph", "agent", "node", "graph", "state", "orchestration", "control flow", "routing", "tools", "execution"] +--- + +# Agent Orchestration Skills + +Advanced patterns for designing and implementing LangGraph-based agent systems. + +## Core Concepts + +### LangGraph Basics +- **Nodes**: Async functions that process state +- **Edges**: Connections between nodes defining flow +- **State**: Shared data structure passed between nodes +- **Conditional Edges**: Route to different nodes based on state +- **Checkpointing**: Persist state for recovery/threading + +### Mind-Bus State Structure +```python +class AgentState: + messages: List[Dict] # Conversation history + thread_id: UUID # Conversation ID + user_id: UUID # User context + memory: List[Memory] # Retrieved memories + context: str # Current context window + compressed: bool # ACC applied flag + tool_calls: List[Dict] # Pending tool executions + response: Optional[str] # LLM response +``` + +## Node Implementation Patterns + +### Retriever Node +Fetch context from memory and knowledge bases. + +```python +async def retriever_node(state: AgentState) -> Dict[str, Any]: + """Retrieve relevant context and memories.""" + + last_msg = next( + (m for m in reversed(state.messages) if m["role"] == "user"), + None + ) + if not last_msg: + return {"memory": [], "context": ""} + + memories = await memory_manager.retrieve( + query=last_msg["content"], + user_id=state.user_id, + limit=5, + similarity_threshold=0.75 + ) + + context = "\n".join([m["content"] for m in memories]) + + return {"memory": memories, "context": context} +``` + +### Planner Node +Decide what actions to take. + +```python +async def planner_node(state: AgentState) -> Dict[str, Any]: + """Plan next actions based on context.""" + + plan_prompt = f"""Given: {state.messages[-1]['content']} + Context: {state.context} + Decide: tool|retrieve|respond""" + + plan = await llm_client.generate(plan_prompt) + + return { + "plan": plan, + "messages": state.messages + [{"role": "planner", "content": plan}] + } +``` + +### Tool Runner Node +Execute tools and collect results. + +```python +async def tool_runner_node(state: AgentState) -> Dict[str, Any]: + """Execute pending tool calls in parallel.""" + + if not state.tool_calls: + return {"tool_results": []} + + tasks = [ + get_tool(call["name"]).execute(**call["arguments"]) + for call in state.tool_calls + ] + + results = await asyncio.gather(*tasks) + + new_messages = state.messages + [ + {"role": "tool", "tool": call["name"], "content": str(r)} + for r, call in zip(results, state.tool_calls) + ] + + return {"tool_results": results, "messages": new_messages} +``` + +### Responder Node +Generate final response. + +```python +async def responder_node(state: AgentState) -> Dict[str, Any]: + """Generate response to user.""" + + response_prompt = f""" + Context: {state.context} + Memory: {[m['content'] for m in state.memory]} + + User: {state.messages[-1]['content']} + + Respond naturally. + """ + + response = await llm_client.generate(response_prompt) + + return { + "response": response, + "messages": state.messages + [{"role": "assistant", "content": response}] + } +``` + +## Graph Design Patterns + +### Sequential Flow +```python +from langgraph.graph import StateGraph + +graph = StateGraph(AgentState) +graph.add_node("retriever", retriever_node) +graph.add_node("planner", planner_node) +graph.add_node("responder", responder_node) + +graph.add_edge("retriever", "planner") +graph.add_edge("planner", "responder") +graph.add_edge("responder", "END") + +graph.set_entry_point("retriever") +agent = graph.compile() +``` + +### Conditional Routing +```python +def route_decision(state: AgentState) -> str: + """Route based on planner decision.""" + return "tool_runner" if "tool" in state.get("plan", "") else "responder" + +graph.add_conditional_edges( + "planner", + route_decision, + {"tool_runner": "tool_runner", "responder": "responder"} +) +graph.add_edge("tool_runner", "responder") +``` + +### Reflection Loop +```python +def should_reflect(state: AgentState) -> str: + """Check if reflection needed.""" + return "reflect" if state.get("needs_improvement") else "END" + +graph.add_node("reflector", reflector_node) +graph.add_conditional_edges( + "responder", + should_reflect, + {"reflect": "reflector", "END": "END"} +) +graph.add_edge("reflector", "responder") # Loop back +``` + +## Running the Agent + +```python +# Create initial state +initial_state = AgentState( + messages=[{"role": "user", "content": "Hello!"}], + thread_id=uuid4(), + user_id=user_id, + memory=[], + context="", + compressed=False +) + +# Run agent +result = agent.invoke(initial_state) + +# Stream results +for step in agent.stream(initial_state): + for node, value in step.items(): + print(f"{node}: {value}") +``` + +## Testing Patterns + +```python +import pytest + +@pytest.mark.asyncio +async def test_retriever_node(): + """Test retriever node.""" + state = AgentState(...) + result = await retriever_node(state) + assert "memory" in result + assert "context" in result + +@pytest.mark.asyncio +async def test_agent_flow(): + """Test full agent flow.""" + agent = build_test_agent() + result = agent.invoke(initial_state) + assert result["response"] is not None +``` + +## References + +- **LangGraph**: https://langgraph.js.org +- **Graph**: `agent/graph.py` +- **Nodes**: `agent/nodes/` +- **State**: `agent/state/state.py` diff --git a/.agents/skills/backend-api/SKILL.md b/.agents/skills/backend-api/SKILL.md new file mode 100644 index 0000000..d21bbed --- /dev/null +++ b/.agents/skills/backend-api/SKILL.md @@ -0,0 +1,418 @@ +--- +name: backend-api +description: "Use when: adding FastAPI routes and endpoints, creating Pydantic schemas, implementing services, adding middleware, handling authentication, or building API features" +keywords: ["fastapi", "endpoint", "route", "schema", "pydantic", "service", "middleware", "jwt", "authentication", "api"] +--- + +# Backend API Skills + +Patterns for building FastAPI endpoints and services in Mind-Bus. + +## Quick Start: Adding an Endpoint + +### 1. Define Schema (Pydantic) +```python +# apps/api/schemas/my_schema.py +from pydantic import BaseModel +from typing import Optional + +class MyRequest(BaseModel): + """Request model.""" + name: str + description: Optional[str] = None + + class Config: + json_schema_extra = { + "example": { + "name": "Test", + "description": "Test description" + } + } + +class MyResponse(BaseModel): + """Response model.""" + id: UUID + name: str + created_at: datetime +``` + +### 2. Create Service +```python +# apps/api/services/my_service.py +from typing import List +from uuid import UUID + +class MyService: + """Business logic layer.""" + + def __init__(self, db): + self.db = db + + async def create_item(self, request: MyRequest, user_id: UUID): + """Create new item.""" + item = await self.db.create( + table="items", + data={ + "name": request.name, + "description": request.description, + "user_id": user_id, + "created_at": datetime.now() + } + ) + return item + + async def get_items(self, user_id: UUID) -> List: + """Get user's items.""" + items = await self.db.query( + "SELECT * FROM items WHERE user_id = ?", + [user_id] + ) + return items +``` + +### 3. Add Route +```python +# apps/api/routes/my_routes.py +from fastapi import APIRouter, Depends, HTTPException, status +from apps.api.security import get_current_user +from apps.api.services.my_service import MyService +from apps.api.schemas.my_schema import MyRequest, MyResponse + +router = APIRouter(prefix="/api/my", tags=["my"]) + +@router.post("/items", response_model=MyResponse) +async def create_item( + request: MyRequest, + current_user: User = Depends(get_current_user), + service: MyService = Depends(get_service) +): + """Create new item.""" + try: + item = await service.create_item(request, current_user.id) + return MyResponse(**item) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e) + ) + +@router.get("/items", response_model=List[MyResponse]) +async def get_items( + current_user: User = Depends(get_current_user), + service: MyService = Depends(get_service) +): + """Get user's items.""" + items = await service.get_items(current_user.id) + return [MyResponse(**item) for item in items] + +@router.get("/items/{item_id}", response_model=MyResponse) +async def get_item( + item_id: UUID, + current_user: User = Depends(get_current_user), + service: MyService = Depends(get_service) +): + """Get specific item.""" + item = await service.get_item(item_id, current_user.id) + if not item: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Item not found" + ) + return MyResponse(**item) +``` + +### 4. Register Route in Main +```python +# apps/api/main.py +from apps.api.routes.my_routes import router as my_router + +app.include_router(my_router) +``` + +## API Patterns + +### Error Handling +```python +from fastapi import HTTPException, status + +@router.post("/endpoint") +async def my_endpoint(request: MyRequest): + """Endpoint with error handling.""" + try: + # Validate input + if not request.name: + raise ValueError("Name is required") + + # Process + result = await process(request) + + return {"success": True, "data": result} + + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e) + ) + except Exception as e: + logger.error(f"Unexpected error: {e}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Internal server error" + ) +``` + +### Dependency Injection +```python +from fastapi import Depends +from apps.api.security import get_current_user + +async def get_service(db: Database = Depends(get_db)) -> MyService: + """Service dependency.""" + return MyService(db) + +@router.get("/items") +async def get_items( + current_user: User = Depends(get_current_user), + service: MyService = Depends(get_service) +): + """Endpoint with dependencies.""" + return await service.get_items(current_user.id) +``` + +### Pagination +```python +from typing import Optional + +class PaginatedResponse(BaseModel): + """Paginated response.""" + items: List[Item] + total: int + page: int + page_size: int + pages: int + +@router.get("/items", response_model=PaginatedResponse) +async def get_items_paginated( + page: int = Query(1, ge=1), + page_size: int = Query(10, ge=1, le=100), + current_user: User = Depends(get_current_user) +): + """Get paginated items.""" + offset = (page - 1) * page_size + + items = await db.query( + "SELECT * FROM items WHERE user_id = ? LIMIT ? OFFSET ?", + [current_user.id, page_size, offset] + ) + + total = await db.scalar( + "SELECT COUNT(*) FROM items WHERE user_id = ?", + [current_user.id] + ) + + return PaginatedResponse( + items=items, + total=total, + page=page, + page_size=page_size, + pages=(total + page_size - 1) // page_size + ) +``` + +### Request/Response Logging +```python +from fastapi import Request +import logging +import json +from uuid import uuid4 + +logger = logging.getLogger(__name__) + +async def log_request_middleware(request: Request, call_next): + """Log all requests.""" + request_id = str(uuid4()) + request.scope["request_id"] = request_id + + body = await request.body() + logger.info( + f"Request: {request_id}", + extra={ + "method": request.method, + "path": request.url.path, + "body": body.decode() if body else None + } + ) + + response = await call_next(request) + + logger.info( + f"Response: {request_id}", + extra={ + "status": response.status_code, + "content_type": response.headers.get("content-type") + } + ) + + return response + +# Add to app +app.add_middleware(middleware_class=type("LoggingMiddleware", + (), + {"dispatch": log_request_middleware})) +``` + +### CORS Configuration +```python +from fastapi.middleware.cors import CORSMiddleware + +app.add_middleware( + CORSMiddleware, + allow_origins=["http://localhost:3000", "https://example.com"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + expose_headers=["Content-Range", "X-Content-Range"] +) +``` + +### Authentication Patterns +```python +# apps/api/security.py +from fastapi import Depends, HTTPException, status +from fastapi.security import HTTPBearer, HTTPAuthCredentials +import jwt + +security = HTTPBearer() + +async def get_current_user( + credentials: HTTPAuthCredentials = Depends(security) +) -> User: + """Validate JWT and return current user.""" + try: + payload = jwt.decode( + credentials.credentials, + settings.JWT_SECRET, + algorithms=["HS256"] + ) + user_id = payload.get("sub") + if not user_id: + raise ValueError("Invalid token") + + user = await db.get_user(user_id) + if not user: + raise ValueError("User not found") + + return user + + except Exception as e: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid credentials" + ) +``` + +### Background Tasks +```python +from fastapi import BackgroundTasks + +@router.post("/process") +async def process_data( + request: ProcessRequest, + background_tasks: BackgroundTasks, + current_user: User = Depends(get_current_user) +): + """Process data in background.""" + + # Queue task + background_tasks.add_task( + long_running_task, + request.data, + current_user.id + ) + + return {"message": "Processing started"} + +async def long_running_task(data: str, user_id: UUID): + """Long running task.""" + result = await expensive_operation(data) + await notify_user(user_id, result) +``` + +## Testing Patterns + +```python +import pytest +from fastapi.testclient import TestClient + +@pytest.fixture +def client(): + """Test client.""" + return TestClient(app) + +def test_create_item(client, mock_service): + """Test item creation.""" + response = client.post( + "/api/my/items", + json={"name": "Test Item"}, + headers={"Authorization": "Bearer test-token"} + ) + + assert response.status_code == 200 + assert response.json()["name"] == "Test Item" + +def test_get_items(client): + """Test item retrieval.""" + response = client.get( + "/api/my/items", + headers={"Authorization": "Bearer test-token"} + ) + + assert response.status_code == 200 + assert isinstance(response.json(), list) + +def test_unauthorized(client): + """Test unauthorized access.""" + response = client.get("/api/my/items") + assert response.status_code == 401 +``` + +## Common Mistakes + +1. **Not Validating Input**: Always use Pydantic schemas + ```python + # ✅ CORRECT + @router.post("/items") + async def create(request: MyRequest): + # request is validated + ``` + +2. **Blocking Operations**: Always use async + ```python + # ❌ WRONG + items = db.query(...) # Blocks event loop + + # ✅ CORRECT + items = await db.query(...) + ``` + +3. **SQL Injection**: Use parameterized queries + ```python + # ✅ CORRECT + await db.query("SELECT * FROM items WHERE id = ?", [id]) + ``` + +## Performance Tips + +1. **Use Dependency Injection**: Reuse dependencies +2. **Cache Responses**: Use Redis for frequently accessed data +3. **Async All The Way**: No blocking calls in routes +4. **Connection Pooling**: Reuse DB connections +5. **Pagination**: Always paginate large result sets + +## References + +- **FastAPI Docs**: https://fastapi.tiangolo.com +- **API Routes**: `apps/api/routes/` +- **Services**: `apps/api/services/` +- **Schemas**: `apps/api/schemas/` +- **Security**: `apps/api/security.py` diff --git a/.agents/skills/frontend-components/SKILL.md b/.agents/skills/frontend-components/SKILL.md new file mode 100644 index 0000000..4043d4b --- /dev/null +++ b/.agents/skills/frontend-components/SKILL.md @@ -0,0 +1,597 @@ +--- +name: frontend-components +description: "Use when: building Vue 3 components, implementing state management with Pinia, adding routes, creating form handling, integrating API calls, or styling with SCSS" +keywords: ["vue3", "typescript", "component", "pinia", "router", "state management", "form", "api", "scss", "vite"] +--- + +# Frontend Components Skills + +Patterns for building Vue 3 TypeScript components in Mind-Bus. + +## Quick Start: Creating a Component + +### 1. Basic Component Structure +```vue + + + + + + +``` + +### 2. Create Pinia Store +```typescript +// src/stores/myStore.ts +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import * as api from '@/services/api' + +export interface Item { + id: string + name: string + description: string + created_at: string +} + +export const useMyStore = defineStore('my', () => { + // State + const items = ref([]) + const isLoading = ref(false) + const selectedItem = ref(null) + + // Computed + const itemCount = computed(() => items.value.length) + const hasItems = computed(() => items.value.length > 0) + + // Actions + async function fetchItems() { + isLoading.value = true + try { + items.value = await api.getItems() + } finally { + isLoading.value = false + } + } + + async function createItem(name: string, description: string) { + const response = await api.createItem({ name, description }) + items.value.push(response) + return response + } + + async function deleteItem(id: string) { + await api.deleteItem(id) + items.value = items.value.filter(item => item.id !== id) + } + + function selectItem(item: Item) { + selectedItem.value = item + } + + // Return public API + return { + // State + items, + isLoading, + selectedItem, + + // Computed + itemCount, + hasItems, + + // Actions + fetchItems, + createItem, + deleteItem, + selectItem + } +}) +``` + +### 3. Add Route +```typescript +// src/router/index.ts +import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' +import { useAuthStore } from '@/stores/auth' +import MyView from '@/views/MyView.vue' + +const routes: RouteRecordRaw[] = [ + { + path: '/my-view', + name: 'MyView', + component: MyView, + meta: { requiresAuth: true } + } +] + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +// Navigation guard +router.beforeEach((to, from, next) => { + const authStore = useAuthStore() + + if (to.meta.requiresAuth && !authStore.isAuthenticated) { + next('/login') + } else { + next() + } +}) + +export default router +``` + +## Component Patterns + +### Reusable Component with Props +```vue + + + + + + +``` + +### Form Component +```vue + +