focus-buddy / src /tools.py
pocanman's picture
migrate to new repo
3006400
Raw
History Blame Contribute Delete
6.59 kB
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