Spaces:
Running on Zero
Running on Zero
| from __future__ import annotations | |
| from src.game_state import get_state | |
| TOOL_SCHEMAS = [ | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "start_timer", | |
| "description": ( | |
| "Start the user's focus timer. Use this when they want to begin a work " | |
| "session, Pomodoro, or free-flow focus block." | |
| ), | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "duration_minutes": { | |
| "type": "integer", | |
| "description": "Duration in minutes (1-180). Ignored in freeflow mode.", | |
| "default": 25, | |
| }, | |
| "mode": { | |
| "type": "string", | |
| "enum": ["pomodoro", "freeflow"], | |
| "description": ( | |
| "'pomodoro' counts down from duration_minutes; " | |
| "'freeflow' counts up indefinitely." | |
| ), | |
| "default": "pomodoro", | |
| }, | |
| }, | |
| "required": [], | |
| }, | |
| }, | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "stop_timer", | |
| "description": "Pause/stop the currently running timer without resetting it.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": {}, | |
| "required": [], | |
| }, | |
| }, | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "reset_timer", | |
| "description": "Stop and reset the timer back to zero, clearing the current session.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": {}, | |
| "required": [], | |
| }, | |
| }, | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "add_todo", | |
| "description": "Add a new task (quest) to the user's todo list.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "task": { | |
| "type": "string", | |
| "description": "The task description to add.", | |
| }, | |
| }, | |
| "required": ["task"], | |
| }, | |
| }, | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "complete_todo", | |
| "description": ( | |
| "Mark an existing task as done. Identify it by its id (preferred, shown " | |
| "as id=N in the quest list) or by matching task text." | |
| ), | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "todo_id": { | |
| "type": "integer", | |
| "description": "The id of the task to complete.", | |
| }, | |
| "task": { | |
| "type": "string", | |
| "description": "Task text to match if the id is unknown.", | |
| }, | |
| }, | |
| "required": [], | |
| }, | |
| }, | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "remove_todo", | |
| "description": ( | |
| "Delete a task from the list entirely. Identify it by its id (preferred) " | |
| "or by matching task text." | |
| ), | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "todo_id": { | |
| "type": "integer", | |
| "description": "The id of the task to remove.", | |
| }, | |
| "task": { | |
| "type": "string", | |
| "description": "Task text to match if the id is unknown.", | |
| }, | |
| }, | |
| "required": [], | |
| }, | |
| }, | |
| }, | |
| ] | |
| def _find_todo(state, arguments: dict) -> dict | None: | |
| """Resolve a todo from a tool's arguments by id (preferred) or task text.""" | |
| tid = arguments.get("todo_id") | |
| if tid is not None: | |
| try: | |
| tid = int(tid) | |
| for t in state.todos: | |
| if t["id"] == tid: | |
| return t | |
| except (ValueError, TypeError): | |
| pass | |
| task = (arguments.get("task") or "").strip().lower() | |
| if task: | |
| for t in state.todos: | |
| if task in t["task"].lower(): | |
| return t | |
| return None | |
| def execute_tool(name: str, arguments: dict) -> tuple[str, str | None]: | |
| """Execute a tool by name. Returns (text_result, js_command_or_None).""" | |
| state = get_state() | |
| if name == "start_timer": | |
| duration = max(1, min(180, int(arguments.get("duration_minutes") or 25))) | |
| mode = arguments.get("mode", "pomodoro") | |
| if mode not in ("pomodoro", "freeflow"): | |
| mode = "pomodoro" | |
| state.timer_state.update({ | |
| "running": True, | |
| "mode": mode, | |
| "duration_minutes": duration, | |
| "phase": "work", | |
| }) | |
| label = f"{duration}-minute {mode}" if mode == "pomodoro" else "free-flow" | |
| js = f"timerStart({duration}, '{mode}')" | |
| return f"Timer started: {label} session.", js | |
| if name == "stop_timer": | |
| state.timer_state["running"] = False | |
| return "Timer stopped.", "timerStop()" | |
| if name == "reset_timer": | |
| state.timer_state.update({"running": False, "phase": "work"}) | |
| return "Timer reset.", "timerReset()" | |
| if name == "add_todo": | |
| task = (arguments.get("task") or "").strip() | |
| if not task: | |
| return "I couldn't tell what task to add.", None | |
| state.add_todo(task) | |
| return f"Added quest: {task}", None | |
| if name == "complete_todo": | |
| t = _find_todo(state, arguments) | |
| if not t: | |
| return "I couldn't find that quest on your list.", None | |
| if t["done"]: | |
| return f"'{t['task']}' is already complete.", None | |
| state.mark_done(t["id"]) | |
| return f"Marked '{t['task']}' complete. +{state.XP_PER_TODO} XP! 🎉", "avatarPlay('questDone')" | |
| if name == "remove_todo": | |
| t = _find_todo(state, arguments) | |
| if not t: | |
| return "I couldn't find that quest on your list.", None | |
| task = t["task"] | |
| state.remove_todo(t["id"]) | |
| return f"Removed quest: {task}", None | |
| return f"Unknown tool: {name}", None | |