personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix sol muse perf: metadata-only loading instead of full agent composition

Replace get_muse_configs() (which calls get_agent/compose_instructions
and loads facet summaries + entities for every tool-using agent) with
direct _load_prompt_metadata() scanning. Same output, 41s → 0.1s.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+45 -8
+45 -8
think/muse_cli.py
··· 28 28 from think.utils import ( 29 29 MUSE_DIR, 30 30 _load_prompt_metadata, 31 - get_muse_configs, 31 + get_config, 32 32 setup_cli, 33 33 ) 34 34 ··· 116 116 source: str | None = None, 117 117 include_disabled: bool = False, 118 118 ) -> dict[str, dict[str, Any]]: 119 - """Collect all muse configs with optional filters applied.""" 120 - configs = get_muse_configs(schedule=schedule, include_disabled=True) 119 + """Collect muse configs using metadata-only loading (no instruction composition). 120 + 121 + This avoids the expensive get_agent() path that compose_instructions() uses, 122 + which loads facet summaries and entity data from the journal. 123 + """ 124 + configs: dict[str, dict[str, Any]] = {} 125 + 126 + # System configs from muse/ 127 + if MUSE_DIR.is_dir(): 128 + for md_path in sorted(MUSE_DIR.glob("*.md")): 129 + info = _load_prompt_metadata(md_path) 130 + info["source"] = "system" 131 + configs[md_path.stem] = info 132 + 133 + # App configs from apps/*/muse/ 134 + apps_dir = _PROJECT_ROOT / "apps" 135 + if apps_dir.is_dir(): 136 + for app_path in sorted(apps_dir.iterdir()): 137 + if not app_path.is_dir() or app_path.name.startswith("_"): 138 + continue 139 + app_muse_dir = app_path / "muse" 140 + if not app_muse_dir.is_dir(): 141 + continue 142 + for md_path in sorted(app_muse_dir.glob("*.md")): 143 + info = _load_prompt_metadata(md_path) 144 + info["source"] = "app" 145 + info["app"] = app_path.name 146 + configs[f"{app_path.name}:{md_path.stem}"] = info 147 + 148 + # Merge journal config overrides (disabled/extract) 149 + overrides = get_config().get("agents", {}) 150 + for key, override in overrides.items(): 151 + if key in configs and isinstance(override, dict): 152 + if "disabled" in override: 153 + configs[key]["disabled"] = override["disabled"] 154 + if "extract" in override: 155 + configs[key]["extract"] = override["extract"] 121 156 157 + # Apply filters 122 158 filtered: dict[str, dict[str, Any]] = {} 123 159 for key, info in configs.items(): 124 160 if not include_disabled and info.get("disabled", False): 161 + continue 162 + if schedule and info.get("schedule") != schedule: 125 163 continue 126 164 if source and info.get("source") != source: 127 165 continue ··· 146 184 include_disabled: bool = False, 147 185 ) -> None: 148 186 """Print prompts grouped by schedule.""" 149 - all_configs = get_muse_configs(include_disabled=True) 150 187 configs = _collect_configs( 151 188 schedule=schedule, source=source, include_disabled=include_disabled 152 189 ) ··· 199 236 200 237 # Show disabled count hint 201 238 if not include_disabled: 202 - disabled_count = sum( 203 - 1 for info in all_configs.values() if info.get("disabled", False) 239 + all_configs = _collect_configs( 240 + schedule=schedule, source=source, include_disabled=True 204 241 ) 242 + disabled_count = len(all_configs) - len(configs) 205 243 if disabled_count: 206 - total = len(configs) 207 - print(f"{total} prompts ({disabled_count} disabled hidden, use --disabled)") 244 + print(f"{len(configs)} prompts ({disabled_count} disabled hidden, use --disabled)") 208 245 209 246 210 247 def show_prompt(name: str, *, as_json: bool = False) -> None: