refactor: split tool declarations into domain files + role config UI
tools/__init__.py shrinks from 1,137 → 250 lines. Each domain file now owns both its callables and its FunctionDeclarations (DECLARATIONS list), so adding a new tool only touches one file. New TOOL_CATEGORIES dict exported from __init__ — used by the UI for grouped tool checkboxes. Role config UI (Settings → Model Registry → Role Assignments): - ⚙ button per role expands an inline configure panel - Textarea for system_append (injected into system prompt for this role) - Grouped checkboxes for tool allow-list (all checked = no restriction) - POST /api/models/role-config saves both fields; updates ROLE_CONFIG_DATA in-page so re-open reflects current state without a page reload Backend: - model_registry.set_role_config() writes system_append + tools to registry - TOOL_CATEGORIES exported from tools/__init__ for UI rendering - TOOLS.md header updated: 30 → 39 tools (ae_journal_* and cortex_* additions) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ API: V3 CRUD — POST /v3/crud/journal_entry/search, POST /v3/crud/journal/{id}
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from google.genai import types
|
||||
from config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -580,3 +581,167 @@ def _sync_journal_entry_prepend(entry_id: str, content: str, heading: str) -> st
|
||||
if result != "ok":
|
||||
return result
|
||||
return f"Prepended to journal entry `{entry_id}` under heading \"{section_heading}\"."
|
||||
|
||||
|
||||
DECLARATIONS = [
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_list",
|
||||
description=(
|
||||
"List all Aether Journals available for this account. "
|
||||
"Returns each journal's name and id_random. "
|
||||
"Call this first when you need to write a new entry or scope a search to a specific journal "
|
||||
"and don't already know the journal's id."
|
||||
),
|
||||
parameters=types.Schema(type=types.Type.OBJECT, properties={}),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_search",
|
||||
description=(
|
||||
"Search Aether Journal entries. All parameters are optional — combine freely. "
|
||||
"Use 'query' for fulltext keyword search (supports boolean: +required -excluded \"phrase\"). "
|
||||
"Use 'tags' to filter by tag substring. Use 'date_from'/'date_to' for date ranges (YYYY-MM-DD). "
|
||||
"Always search before creating a new entry to avoid duplicates."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"query": types.Schema(type=types.Type.STRING, description="Fulltext keyword search. Supports boolean mode: +required -excluded \"exact phrase\"."),
|
||||
"journal_id": types.Schema(type=types.Type.STRING, description="Scope results to a specific journal by its id_random. Omit to search all journals."),
|
||||
"tags": types.Schema(type=types.Type.STRING, description="Filter by tag substring (e.g. 'networking' matches entries tagged 'networking' or 'home-networking')."),
|
||||
"type_code": types.Schema(type=types.Type.STRING, description="Filter by exact type_code (e.g. 'note', 'meeting', 'log')."),
|
||||
"topic_code": types.Schema(type=types.Type.STRING, description="Filter by exact topic_code."),
|
||||
"date_from": types.Schema(type=types.Type.STRING, description="Return entries created on or after this date (YYYY-MM-DD)."),
|
||||
"date_to": types.Schema(type=types.Type.STRING, description="Return entries created on or before this date (YYYY-MM-DD)."),
|
||||
"sort_by": types.Schema(type=types.Type.STRING, description="Sort field: 'updated' (default), 'created', 'name', or 'priority'."),
|
||||
"sort_order": types.Schema(type=types.Type.STRING, description="Sort direction: 'desc' (default, newest first) or 'asc'."),
|
||||
"status": types.Schema(type=types.Type.INTEGER, description="Filter by exact status code."),
|
||||
"priority": types.Schema(type=types.Type.INTEGER, description="Filter by exact priority (1=low, 5=high)."),
|
||||
"max_results": types.Schema(type=types.Type.INTEGER, description="Number of results per page (default 10)."),
|
||||
"page": types.Schema(type=types.Type.INTEGER, description="Page number for pagination (default 1)."),
|
||||
},
|
||||
required=[],
|
||||
),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_entry_read",
|
||||
description=(
|
||||
"Fetch the full content of a single journal entry by its id_random. "
|
||||
"Use this when you need to read an entry before editing it, or when search results "
|
||||
"don't show enough content. Returns title, journal, tags, summary, and full content."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"entry_id": types.Schema(type=types.Type.STRING, description="The id_random of the journal entry to read."),
|
||||
"max_content_chars": types.Schema(type=types.Type.INTEGER, description="Maximum characters of content to return (default 4000). Increase for long entries."),
|
||||
},
|
||||
required=["entry_id"],
|
||||
),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_entries_list",
|
||||
description=(
|
||||
"List entries in a specific journal, newest first. "
|
||||
"Use this to browse what's in a journal when you don't have a search keyword, "
|
||||
"or to find entries by browsing rather than searching. "
|
||||
"Returns numbered entries with id, title, tags, summary, and date."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"journal_id": types.Schema(type=types.Type.STRING, description="The id_random of the journal to list entries from."),
|
||||
"max_results": types.Schema(type=types.Type.INTEGER, description="Number of entries to return (default 20, max 50)."),
|
||||
"page": types.Schema(type=types.Type.INTEGER, description="Page number for pagination (default 1)."),
|
||||
},
|
||||
required=["journal_id"],
|
||||
),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_entry_create",
|
||||
description=(
|
||||
"Create a new entry in an Aether Journal. "
|
||||
"Use this to save notes, summaries, or any content the user wants to store. "
|
||||
"Always call ae_journal_search first to check for existing entries on the same topic."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"journal_id": types.Schema(type=types.Type.STRING, description="The id_random of the target journal. Ask the user which journal to write to if not specified."),
|
||||
"title": types.Schema(type=types.Type.STRING, description="Entry title"),
|
||||
"content": types.Schema(type=types.Type.STRING, description="Full entry content (markdown supported)"),
|
||||
"summary": types.Schema(type=types.Type.STRING, description="Optional short summary (1-2 sentences)"),
|
||||
"tags": types.Schema(type=types.Type.STRING, description="Optional comma-separated tags (e.g. 'wireguard, networking, homelab')"),
|
||||
},
|
||||
required=["journal_id", "title", "content"],
|
||||
),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_entry_update",
|
||||
description=(
|
||||
"Update fields on an existing journal entry. Only the fields you provide are changed — "
|
||||
"omitted fields are left as-is. Use ae_journal_search to find the entry_id first. "
|
||||
"To soft-delete, use ae_journal_entry_disable instead."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"entry_id": types.Schema(type=types.Type.STRING, description="Journal entry id_random"),
|
||||
"title": types.Schema(type=types.Type.STRING, description="New title"),
|
||||
"content": types.Schema(type=types.Type.STRING, description="Replacement content (full, markdown supported)"),
|
||||
"summary": types.Schema(type=types.Type.STRING, description="New summary"),
|
||||
"tags": types.Schema(type=types.Type.STRING, description="Replacement comma-separated tags"),
|
||||
"enable": types.Schema(type=types.Type.BOOLEAN, description="Set false to hide/disable the entry"),
|
||||
},
|
||||
required=["entry_id"],
|
||||
),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_entry_disable",
|
||||
description=(
|
||||
"Soft-delete a journal entry by setting enable=false. "
|
||||
"The entry is hidden but not permanently removed. "
|
||||
"Use ae_journal_search to find the entry_id first."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"entry_id": types.Schema(type=types.Type.STRING, description="Journal entry id_random"),
|
||||
},
|
||||
required=["entry_id"],
|
||||
),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_entry_append",
|
||||
description=(
|
||||
"Append a new section to the bottom of a journal entry's content. "
|
||||
"Each section gets a UTC timestamp heading unless you provide one. "
|
||||
"Ideal for timestamped logs, running notes, or data logs."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"entry_id": types.Schema(type=types.Type.STRING, description="Journal entry id_random"),
|
||||
"content": types.Schema(type=types.Type.STRING, description="The text to append (markdown supported)"),
|
||||
"heading": types.Schema(type=types.Type.STRING, description="Optional section heading (defaults to current UTC timestamp)"),
|
||||
},
|
||||
required=["entry_id", "content"],
|
||||
),
|
||||
),
|
||||
types.FunctionDeclaration(
|
||||
name="ae_journal_entry_prepend",
|
||||
description=(
|
||||
"Prepend a new section to the top of a journal entry's content. "
|
||||
"Each section gets a UTC timestamp heading unless you provide one. "
|
||||
"Useful for most-recent-first logs."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"entry_id": types.Schema(type=types.Type.STRING, description="Journal entry id_random"),
|
||||
"content": types.Schema(type=types.Type.STRING, description="The text to prepend (markdown supported)"),
|
||||
"heading": types.Schema(type=types.Type.STRING, description="Optional section heading (defaults to current UTC timestamp)"),
|
||||
},
|
||||
required=["entry_id", "content"],
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user