personal memory agent
at main 111 lines 3.7 kB view raw
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3 4"""Generate AGENTS.md from sol/identity.md using journal config values.""" 5 6from __future__ import annotations 7 8import json 9import os 10from pathlib import Path 11from string import Template 12from typing import Any 13 14PROJECT_ROOT = Path(__file__).resolve().parent.parent 15DEFAULT_CONFIG_PATH = PROJECT_ROOT / "think" / "journal_default.json" 16SOURCE_PATH = PROJECT_ROOT / "sol" / "identity.md" 17OUTPUT_PATH = PROJECT_ROOT / "AGENTS.md" 18GENERATED_HEADER = "<!-- generated from sol/identity.md — do not edit directly -->\n\n" 19 20 21def _load_config() -> dict[str, Any]: 22 with open(DEFAULT_CONFIG_PATH, "r", encoding="utf-8") as f: 23 config = json.load(f) 24 25 journal_root = os.getenv("_SOLSTONE_JOURNAL_OVERRIDE") 26 if journal_root: 27 journal_path = Path(journal_root) 28 if not journal_path.is_absolute(): 29 journal_path = PROJECT_ROOT / journal_path 30 else: 31 journal_path = PROJECT_ROOT / "journal" 32 33 config_path = journal_path / "config" / "journal.json" 34 if not config_path.exists(): 35 return config 36 37 with open(config_path, "r", encoding="utf-8") as f: 38 return json.load(f) 39 40 41def _flatten_identity_to_template_vars(identity: dict[str, Any]) -> dict[str, str]: 42 template_vars: dict[str, str] = {} 43 44 for key, value in identity.items(): 45 if isinstance(value, dict): 46 for subkey, subvalue in value.items(): 47 var_name = f"{key}_{subkey}" 48 template_vars[var_name] = str(subvalue) 49 template_vars[var_name.capitalize()] = str(subvalue).capitalize() 50 elif isinstance(value, (str, int, float, bool)): 51 template_vars[key] = str(value) 52 template_vars[key.capitalize()] = str(value).capitalize() 53 54 return template_vars 55 56 57def _apply_human_defaults( 58 template_vars: dict[str, str], config: dict[str, Any] 59) -> None: 60 agent_name = str(config.get("agent", {}).get("name", "sol")) 61 template_vars["agent_name"] = agent_name 62 template_vars["Agent_name"] = agent_name.capitalize() 63 64 resolved_name = template_vars.get("name", "") or "your journal owner" 65 resolved_preferred = template_vars.get("preferred", "") or resolved_name 66 67 template_vars["name"] = resolved_name 68 template_vars["Name"] = resolved_name.capitalize() 69 template_vars["preferred"] = resolved_preferred 70 template_vars["Preferred"] = resolved_preferred.capitalize() 71 72 pronoun_defaults = { 73 "subject": "they", 74 "object": "them", 75 "possessive": "their", 76 "reflexive": "themselves", 77 } 78 for key, value in pronoun_defaults.items(): 79 var_name = f"pronouns_{key}" 80 resolved = template_vars.get(var_name, "") or value 81 template_vars[var_name] = resolved 82 template_vars[var_name.capitalize()] = resolved.capitalize() 83 84 85def _load_template_body() -> str: 86 with open(SOURCE_PATH, "r", encoding="utf-8") as f: 87 lines = f.readlines() 88 for i, line in enumerate(lines): 89 if line.strip() == "}": 90 return "".join(lines[i + 1 :]) 91 return "".join(lines) 92 93 94def main() -> None: 95 config = _load_config() 96 identity = config.get("identity", {}) 97 template_vars = _flatten_identity_to_template_vars(identity) 98 _apply_human_defaults(template_vars, config) 99 100 content = _load_template_body() 101 rendered = Template(content).safe_substitute(template_vars) 102 103 with open(OUTPUT_PATH, "w", encoding="utf-8") as f: 104 f.write(GENERATED_HEADER) 105 f.write(rendered) 106 107 print("Generated AGENTS.md from sol/identity.md") 108 109 110if __name__ == "__main__": 111 main()