"""User profile tools — preferences, routines, and work session management.""" from tools import tool from user_profile import ( get_preferences, set_preference, get_preference, set_user_name, add_routine_entry, update_routine_entry, get_today_routine, get_routine_history, start_work_session, add_work_note, end_work_session, get_last_work_session, get_active_work_session, get_work_history, ) # ── Preferences ──────────────────────────────────────────────────── @tool( name="set_user_preference", description="Save a user preference (e.g. theme, language, schedule, habits). Persists to cloud.", parameters={ "type": "object", "properties": { "key": {"type": "string", "description": "Preference key (e.g. 'wake_time', 'theme', 'language')"}, "value": {"type": "string", "description": "Preference value"}, }, "required": ["key", "value"], }, ) async def set_user_preference_tool(key: str, value: str) -> str: await set_preference(key, value) return f"Preference saved: {key} = {value}" @tool( name="get_user_preference", description="Retrieve a specific user preference", parameters={ "type": "object", "properties": { "key": {"type": "string", "description": "Preference key to look up"}, }, "required": ["key"], }, ) async def get_user_preference_tool(key: str) -> str: val = await get_preference(key) if val is None: return f"No preference found for '{key}'" return f"{key} = {val}" @tool( name="get_all_preferences", description="Get all saved user preferences", parameters={"type": "object", "properties": {}}, ) async def get_all_preferences_tool() -> str: profile = await get_preferences() prefs = profile.get("preferences", {}) if not prefs: return "No preferences saved yet." lines = [f" {k}: {v}" for k, v in prefs.items()] name = profile.get("name", "") header = f"User: {name}\n" if name else "" return header + "Preferences:\n" + "\n".join(lines) @tool( name="set_my_name", description="Set the user's name so JARVIS can address them personally", parameters={ "type": "object", "properties": { "name": {"type": "string", "description": "User's name"}, }, "required": ["name"], }, ) async def set_my_name_tool(name: str) -> str: await set_user_name(name) return f"Name set to: {name}" # ── Daily Routines ───────────────────────────────────────────────── @tool( name="add_routine", description="Add an activity to today's daily routine/schedule", parameters={ "type": "object", "properties": { "activity": {"type": "string", "description": "Activity description (e.g. 'morning standup')"}, "time": {"type": "string", "description": "Time in HH:MM format (optional, defaults to now)"}, }, "required": ["activity"], }, ) async def add_routine_tool(activity: str, time: str = "") -> str: routine = await add_routine_entry(activity, time) return f"Added to routine: {time or 'now'} — {activity}\nTotal entries today: {len(routine.get('entries', []))}" @tool( name="complete_routine", description="Mark a routine entry as completed by its index (0-based)", parameters={ "type": "object", "properties": { "index": {"type": "integer", "description": "Entry index (0-based)"}, }, "required": ["index"], }, ) async def complete_routine_tool(index: int) -> str: routine = await update_routine_entry(index, "completed") entries = routine.get("entries", []) if 0 <= index < len(entries): return f"Marked as completed: {entries[index]['activity']}" return "Invalid entry index." @tool( name="show_routine", description="Show today's daily routine / schedule", parameters={"type": "object", "properties": {}}, ) async def show_routine_tool() -> str: routine = await get_today_routine() entries = routine.get("entries", []) if not entries: return "No routine entries for today yet." lines = [f"Today's Routine ({routine['date']}):"] for i, e in enumerate(entries): icon = {"completed": "✓", "in_progress": "→", "pending": "○"}.get( e.get("status", "pending"), "○" ) lines.append(f" {i}. {icon} {e.get('time', '??:??')} — {e['activity']}") return "\n".join(lines) @tool( name="routine_history", description="Show routine history for the past N days", parameters={ "type": "object", "properties": { "days": {"type": "integer", "description": "Number of days to look back (default 7)"}, }, }, ) async def routine_history_tool(days: int = 7) -> str: history = await get_routine_history(days) if not history: return "No routine history found." lines = [] for r in history: entries = r.get("entries", []) completed = sum(1 for e in entries if e.get("status") == "completed") lines.append(f"{r['date']}: {completed}/{len(entries)} completed") for e in entries: icon = "✓" if e.get("status") == "completed" else "○" lines.append(f" {icon} {e.get('time', '')} {e['activity']}") return "\n".join(lines) # ── Work Sessions ────────────────────────────────────────────────── @tool( name="start_work", description="Start tracking a new work session (auto-ends previous if active)", parameters={ "type": "object", "properties": { "title": {"type": "string", "description": "What you're working on"}, "description": {"type": "string", "description": "Details about the work (optional)"}, "tags": {"type": "string", "description": "Comma-separated tags (optional)"}, }, "required": ["title"], }, ) async def start_work_tool(title: str, description: str = "", tags: str = "") -> str: tag_list = [t.strip() for t in tags.split(",") if t.strip()] if tags else [] session = await start_work_session(title, description, tag_list) return f"Work session started: {title}\nSession ID: {session['id']}" @tool( name="work_note", description="Add a note to the current active work session (progress, blockers, etc.)", parameters={ "type": "object", "properties": { "note": {"type": "string", "description": "Note to add"}, }, "required": ["note"], }, ) async def work_note_tool(note: str) -> str: session = await add_work_note(note) if session is None: return "No active work session. Use start_work first." return f"Note added to '{session['title']}' ({len(session['notes'])} total notes)" @tool( name="end_work", description="End the current work session with an optional summary", parameters={ "type": "object", "properties": { "summary": {"type": "string", "description": "Brief summary of what was accomplished"}, }, }, ) async def end_work_tool(summary: str = "") -> str: session = await end_work_session(summary) if session is None: return "No active work session to end." return f"Work session ended: {session['title']}\nDuration: {session['started_at']} → {session['ended_at']}" @tool( name="current_work", description="Show the currently active work session", parameters={"type": "object", "properties": {}}, ) async def current_work_tool() -> str: session = await get_active_work_session() if session is None: return "No active work session." lines = [ f"Active Session: {session['title']}", f" Started: {session['started_at']}", ] if session.get("description"): lines.append(f" Description: {session['description']}") if session.get("tags"): lines.append(f" Tags: {', '.join(session['tags'])}") if session.get("notes"): lines.append(f" Notes ({len(session['notes'])}):") for n in session["notes"][-5:]: lines.append(f" - {n['text']}") return "\n".join(lines) @tool( name="last_work", description="Show the most recent completed work session", parameters={"type": "object", "properties": {}}, ) async def last_work_tool() -> str: session = await get_last_work_session() if session is None: return "No work sessions recorded yet." lines = [ f"Last Session: {session['title']} [{session.get('status', 'unknown')}]", f" Started: {session.get('started_at', '?')}", f" Ended: {session.get('ended_at', 'still active')}", ] if session.get("tags"): lines.append(f" Tags: {', '.join(session['tags'])}") if session.get("notes"): lines.append(f" Notes:") for n in session["notes"][-5:]: lines.append(f" - {n['text']}") return "\n".join(lines) @tool( name="work_history", description="Show recent work session history", parameters={ "type": "object", "properties": { "limit": {"type": "integer", "description": "Number of sessions to show (default 10)"}, }, }, ) async def work_history_tool(limit: int = 10) -> str: sessions = await get_work_history(limit) if not sessions: return "No work sessions recorded yet." lines = ["Work History:"] for s in sessions: status = {"in_progress": "→", "completed": "✓", "paused": "⏸"}.get( s.get("status", ""), "?" ) tags = f" [{', '.join(s['tags'])}]" if s.get("tags") else "" lines.append(f" {status} {s['title']}{tags} — {s.get('started_at', '?')}") return "\n".join(lines)