feat: reminders_add and reminders_list tools
- New cortex/tools/reminders.py with reminders_add, reminders_list, reminders_clear - reminders_clear moved here from cron.py (cron still imports from same file) - __init__.py: wired up new callables and Gemini declarations - Inara can now add/read reminders in Agent mode via the orchestrator Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,10 @@ from tools.cron import (
|
|||||||
cron_add as _cron_add,
|
cron_add as _cron_add,
|
||||||
cron_remove as _cron_remove,
|
cron_remove as _cron_remove,
|
||||||
cron_toggle as _cron_toggle,
|
cron_toggle as _cron_toggle,
|
||||||
|
)
|
||||||
|
from tools.reminders import (
|
||||||
|
reminders_add as _reminders_add,
|
||||||
|
reminders_list as _reminders_list,
|
||||||
reminders_clear as _reminders_clear,
|
reminders_clear as _reminders_clear,
|
||||||
)
|
)
|
||||||
from tools.scratch import (
|
from tools.scratch import (
|
||||||
@@ -196,6 +200,8 @@ _CALLABLES: dict[str, callable] = {
|
|||||||
"cron_add": _cron_add,
|
"cron_add": _cron_add,
|
||||||
"cron_remove": _cron_remove,
|
"cron_remove": _cron_remove,
|
||||||
"cron_toggle": _cron_toggle,
|
"cron_toggle": _cron_toggle,
|
||||||
|
"reminders_add": _reminders_add,
|
||||||
|
"reminders_list": _reminders_list,
|
||||||
"reminders_clear": _reminders_clear,
|
"reminders_clear": _reminders_clear,
|
||||||
"scratch_read": _scratch_read,
|
"scratch_read": _scratch_read,
|
||||||
"scratch_write": _scratch_write,
|
"scratch_write": _scratch_write,
|
||||||
@@ -409,6 +415,40 @@ _cron_toggle_declaration = types.FunctionDeclaration(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_reminders_add_declaration = types.FunctionDeclaration(
|
||||||
|
name="reminders_add",
|
||||||
|
description=(
|
||||||
|
"Add a new reminder to REMINDERS.md. Reminders are automatically surfaced "
|
||||||
|
"in your context at the start of each session (Tier 2+). "
|
||||||
|
"Use this when the user asks you to remember something, follow up on something, "
|
||||||
|
"or surface a note at the next session."
|
||||||
|
),
|
||||||
|
parameters=types.Schema(
|
||||||
|
type=types.Type.OBJECT,
|
||||||
|
properties={
|
||||||
|
"text": types.Schema(
|
||||||
|
type=types.Type.STRING,
|
||||||
|
description="The reminder text to add",
|
||||||
|
),
|
||||||
|
"label": types.Schema(
|
||||||
|
type=types.Type.STRING,
|
||||||
|
description="Optional heading for this reminder (e.g. 'Follow up on NC Talk'). Defaults to current timestamp.",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
required=["text"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
_reminders_list_declaration = types.FunctionDeclaration(
|
||||||
|
name="reminders_list",
|
||||||
|
description=(
|
||||||
|
"Read all current pending reminders from REMINDERS.md. "
|
||||||
|
"Use this to check what reminders are queued before adding duplicates, "
|
||||||
|
"or to show the user what's pending."
|
||||||
|
),
|
||||||
|
parameters=types.Schema(type=types.Type.OBJECT, properties={}),
|
||||||
|
)
|
||||||
|
|
||||||
_reminders_clear_declaration = types.FunctionDeclaration(
|
_reminders_clear_declaration = types.FunctionDeclaration(
|
||||||
name="reminders_clear",
|
name="reminders_clear",
|
||||||
description=(
|
description=(
|
||||||
@@ -494,6 +534,8 @@ TOOL_DECLARATIONS = [
|
|||||||
_cron_add_declaration,
|
_cron_add_declaration,
|
||||||
_cron_remove_declaration,
|
_cron_remove_declaration,
|
||||||
_cron_toggle_declaration,
|
_cron_toggle_declaration,
|
||||||
|
_reminders_add_declaration,
|
||||||
|
_reminders_list_declaration,
|
||||||
_reminders_clear_declaration,
|
_reminders_clear_declaration,
|
||||||
_scratch_read_declaration,
|
_scratch_read_declaration,
|
||||||
_scratch_write_declaration,
|
_scratch_write_declaration,
|
||||||
|
|||||||
69
cortex/tools/reminders.py
Normal file
69
cortex/tools/reminders.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
"""
|
||||||
|
Reminders tools.
|
||||||
|
|
||||||
|
Reminders are stored in persona/REMINDERS.md and automatically surfaced
|
||||||
|
in the system prompt at Tier 2+. Use these tools to add, list, and clear
|
||||||
|
pending reminders.
|
||||||
|
|
||||||
|
Operations:
|
||||||
|
reminders_add — append a new reminder entry
|
||||||
|
reminders_list — return all current reminders (or a message if empty)
|
||||||
|
reminders_clear — erase all reminders (moved here from cron.py for consistency;
|
||||||
|
cron.py still calls the same underlying file)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from persona import persona_path
|
||||||
|
|
||||||
|
|
||||||
|
def _reminders_path() -> Path:
|
||||||
|
return persona_path() / "REMINDERS.md"
|
||||||
|
|
||||||
|
|
||||||
|
def _now_label() -> str:
|
||||||
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Sync implementations
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _reminders_list() -> str:
|
||||||
|
p = _reminders_path()
|
||||||
|
if not p.exists() or not p.read_text().strip():
|
||||||
|
return "No pending reminders."
|
||||||
|
return p.read_text()
|
||||||
|
|
||||||
|
|
||||||
|
def _reminders_add(text: str, label: str | None = None) -> str:
|
||||||
|
p = _reminders_path()
|
||||||
|
existing = p.read_text() if p.exists() else ""
|
||||||
|
heading = label or _now_label()
|
||||||
|
section = f"\n## {heading}\n\n{text.strip()}\n"
|
||||||
|
p.write_text(existing.rstrip() + "\n" + section)
|
||||||
|
return f"Reminder added: {heading}"
|
||||||
|
|
||||||
|
|
||||||
|
def _reminders_clear() -> str:
|
||||||
|
p = _reminders_path()
|
||||||
|
p.write_text("")
|
||||||
|
return "All reminders cleared."
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Async wrappers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
async def reminders_list() -> str:
|
||||||
|
return await asyncio.to_thread(_reminders_list)
|
||||||
|
|
||||||
|
|
||||||
|
async def reminders_add(text: str, label: str | None = None) -> str:
|
||||||
|
return await asyncio.to_thread(_reminders_add, text, label)
|
||||||
|
|
||||||
|
|
||||||
|
async def reminders_clear() -> str:
|
||||||
|
return await asyncio.to_thread(_reminders_clear)
|
||||||
Reference in New Issue
Block a user