personal memory agent
at main 127 lines 4.6 kB view raw
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3 4"""Tool functions for facet management. 5 6These functions can be imported and called directly from agent workflows, 7tests, or other internal modules. 8""" 9 10from pathlib import Path 11from typing import Any 12 13from think.facets import facet_summary 14from think.utils import get_journal 15 16 17def get_facet(facet: str) -> dict[str, Any]: 18 """Get a comprehensive summary of a facet including its metadata and entities. 19 20 This tool generates a formatted markdown summary for a specified facet in the journal. 21 The summary includes the facet's title, description, and tracked entities. 22 Use this when you need an overview of a facet's current state and its associated entities. 23 24 Args: 25 facet: The facet name to retrieve the summary for 26 27 Returns: 28 Dictionary containing: 29 - facet: The facet name that was queried 30 - summary: Formatted markdown text with the complete facet summary including: 31 - Facet title 32 - Facet description 33 - List of tracked entities 34 35 Examples: 36 - get_facet("personal") 37 - get_facet("work_projects") 38 - get_facet("research") 39 40 Returns: 41 If the facet doesn't exist, returns an error dictionary with an error message 42 and suggestion for resolution. 43 """ 44 try: 45 # Get the facet summary markdown 46 summary_text = facet_summary(facet) 47 return {"facet": facet, "summary": summary_text} 48 except FileNotFoundError: 49 return { 50 "error": f"Facet '{facet}' not found", 51 "suggestion": "verify the facet name exists in the journal", 52 } 53 except Exception as exc: 54 return { 55 "error": f"Failed to get facet summary: {exc}", 56 "suggestion": "check that the facet exists and has valid metadata", 57 } 58 59 60def facet_news(facet: str, day: str, markdown: str | None = None) -> dict[str, Any]: 61 """Read or write news for a specific facet and day. 62 63 This tool manages facet-specific news stored in markdown files organized by date. 64 When markdown content is provided, it writes/updates the news file for that day. 65 When markdown is not provided, it reads and returns the existing news for that day. 66 News files are stored as `facets/<facet>/news/YYYYMMDD.md`. 67 68 Args: 69 facet: The facet name to manage news for 70 day: The day in YYYYMMDD format 71 markdown: Optional markdown content to write. If not provided, reads existing news. 72 Should follow the format with dated header and news entries with source/time. 73 74 Returns: 75 Dictionary containing either: 76 - facet, day, and news content when reading 77 - facet, day, and success message when writing 78 - error and suggestion if operation fails 79 80 Examples: 81 - facet_news("ml_research", "20250118") # Read news for the day 82 - facet_news("work", "20250118", "# 2025-01-18 News...") # Write news 83 """ 84 try: 85 journal_path = Path(get_journal()) 86 facet_path = journal_path / "facets" / facet 87 88 # Check if facet exists 89 if not facet_path.exists(): 90 return { 91 "error": f"Facet '{facet}' not found", 92 "suggestion": "Create the facet first or check the facet name", 93 } 94 95 # Ensure news directory exists 96 news_dir = facet_path / "news" 97 news_dir.mkdir(exist_ok=True) 98 99 # Path to the specific day's news file 100 news_file = news_dir / f"{day}.md" 101 102 if markdown is not None: 103 # Write mode - save the markdown content 104 news_file.write_text(markdown, encoding="utf-8") 105 return { 106 "facet": facet, 107 "day": day, 108 "message": f"News for {day} saved successfully in facet '{facet}'", 109 } 110 else: 111 # Read mode - return existing news or empty message 112 if news_file.exists(): 113 news_content = news_file.read_text(encoding="utf-8") 114 return {"facet": facet, "day": day, "news": news_content} 115 else: 116 return { 117 "facet": facet, 118 "day": day, 119 "news": None, 120 "message": f"No news recorded for {day} in facet '{facet}'", 121 } 122 123 except Exception as exc: 124 return { 125 "error": f"Failed to process facet news: {exc}", 126 "suggestion": "check facet exists and has proper permissions", 127 }