claude-memory-agent 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +11 -1
- package/bin/lib/banner.js +39 -0
- package/bin/lib/environment.js +166 -0
- package/bin/lib/installer.js +291 -0
- package/bin/lib/models.js +95 -0
- package/bin/lib/steps/advanced.js +101 -0
- package/bin/lib/steps/confirm.js +87 -0
- package/bin/lib/steps/model.js +57 -0
- package/bin/lib/steps/provider.js +65 -0
- package/bin/lib/steps/scope.js +59 -0
- package/bin/lib/steps/server.js +74 -0
- package/bin/lib/ui.js +75 -0
- package/bin/onboarding.js +164 -0
- package/bin/postinstall.js +22 -257
- package/config.py +103 -4
- package/dashboard.html +697 -27
- package/hooks/extract_memories.py +439 -0
- package/hooks/pre_compact_hook.py +76 -0
- package/hooks/session_end_hook.py +149 -0
- package/hooks/stop_hook.py +372 -0
- package/install.py +85 -32
- package/main.py +1636 -892
- package/mcp_server.py +451 -0
- package/package.json +14 -3
- package/requirements.txt +12 -8
- package/services/adaptive_ranker.py +272 -0
- package/services/agent_catalog.json +153 -0
- package/services/agent_registry.py +245 -730
- package/services/claude_md_sync.py +320 -4
- package/services/consolidation.py +417 -0
- package/services/database.py +586 -105
- package/services/embedding_pipeline.py +262 -0
- package/services/embeddings.py +493 -85
- package/services/memory_decay.py +408 -0
- package/services/native_memory_paths.py +86 -0
- package/services/native_memory_sync.py +496 -0
- package/services/response_manager.py +183 -0
- package/services/terminal_ui.py +199 -0
- package/services/tier_manager.py +235 -0
- package/services/websocket.py +26 -6
- package/skills/search.py +136 -61
- package/skills/session_review.py +210 -23
- package/skills/store.py +125 -18
- package/terminal_dashboard.py +474 -0
- package/hooks/__pycache__/auto-detect-response.cpython-312.pyc +0 -0
- package/hooks/__pycache__/auto_capture.cpython-312.pyc +0 -0
- package/hooks/__pycache__/grounding-hook.cpython-312.pyc +0 -0
- package/hooks/__pycache__/session_end.cpython-312.pyc +0 -0
- package/hooks/__pycache__/session_start.cpython-312.pyc +0 -0
- package/services/__pycache__/__init__.cpython-312.pyc +0 -0
- package/services/__pycache__/agent_registry.cpython-312.pyc +0 -0
- package/services/__pycache__/auth.cpython-312.pyc +0 -0
- package/services/__pycache__/auto_inject.cpython-312.pyc +0 -0
- package/services/__pycache__/claude_md_sync.cpython-312.pyc +0 -0
- package/services/__pycache__/cleanup.cpython-312.pyc +0 -0
- package/services/__pycache__/compaction_flush.cpython-312.pyc +0 -0
- package/services/__pycache__/confidence.cpython-312.pyc +0 -0
- package/services/__pycache__/curator.cpython-312.pyc +0 -0
- package/services/__pycache__/daily_log.cpython-312.pyc +0 -0
- package/services/__pycache__/database.cpython-312.pyc +0 -0
- package/services/__pycache__/embeddings.cpython-312.pyc +0 -0
- package/services/__pycache__/insights.cpython-312.pyc +0 -0
- package/services/__pycache__/llm_analyzer.cpython-312.pyc +0 -0
- package/services/__pycache__/memory_md_sync.cpython-312.pyc +0 -0
- package/services/__pycache__/retry_queue.cpython-312.pyc +0 -0
- package/services/__pycache__/timeline.cpython-312.pyc +0 -0
- package/services/__pycache__/vector_index.cpython-312.pyc +0 -0
- package/services/__pycache__/websocket.cpython-312.pyc +0 -0
- package/skills/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/__pycache__/admin.cpython-312.pyc +0 -0
- package/skills/__pycache__/checkpoint.cpython-312.pyc +0 -0
- package/skills/__pycache__/claude_md.cpython-312.pyc +0 -0
- package/skills/__pycache__/cleanup.cpython-312.pyc +0 -0
- package/skills/__pycache__/confidence_tracker.cpython-312.pyc +0 -0
- package/skills/__pycache__/context.cpython-312.pyc +0 -0
- package/skills/__pycache__/curator.cpython-312.pyc +0 -0
- package/skills/__pycache__/grounding.cpython-312.pyc +0 -0
- package/skills/__pycache__/insights.cpython-312.pyc +0 -0
- package/skills/__pycache__/natural_language.cpython-312.pyc +0 -0
- package/skills/__pycache__/retrieve.cpython-312.pyc +0 -0
- package/skills/__pycache__/search.cpython-312.pyc +0 -0
- package/skills/__pycache__/session_review.cpython-312.pyc +0 -0
- package/skills/__pycache__/state.cpython-312.pyc +0 -0
- package/skills/__pycache__/store.cpython-312.pyc +0 -0
- package/skills/__pycache__/summarize.cpython-312.pyc +0 -0
- package/skills/__pycache__/timeline.cpython-312.pyc +0 -0
- package/skills/__pycache__/verification.cpython-312.pyc +0 -0
- package/test_automation.py +0 -221
- package/test_complete.py +0 -338
- package/test_full.py +0 -322
- package/verify_db.py +0 -134
|
@@ -1,738 +1,253 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Agent Registry -
|
|
2
|
+
Agent Registry - Loads agent/MCP/hook catalogs from JSON data file.
|
|
3
|
+
|
|
4
|
+
Static display metadata lives in agent_catalog.json (~880 entries).
|
|
5
|
+
Dynamic loading (hooks, MCPs) reads Claude Code settings files at runtime
|
|
6
|
+
to determine which entries are truly configured.
|
|
3
7
|
"""
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
# Engineering - Core
|
|
84
|
-
{
|
|
85
|
-
"id": "general-purpose",
|
|
86
|
-
"name": "General Purpose",
|
|
87
|
-
"category": "engineering",
|
|
88
|
-
"description": "Multi-step task handler for complex research and code execution.",
|
|
89
|
-
"tags": ["general", "multi-step", "research"],
|
|
90
|
-
"default_enabled": True,
|
|
91
|
-
"priority": 10
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
"id": "Bash",
|
|
95
|
-
"name": "Bash Specialist",
|
|
96
|
-
"category": "engineering",
|
|
97
|
-
"description": "Command execution specialist for git, terminal operations, and system tasks.",
|
|
98
|
-
"tags": ["bash", "git", "terminal"],
|
|
99
|
-
"default_enabled": True,
|
|
100
|
-
"priority": 9
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
"id": "engineering-senior-developer",
|
|
104
|
-
"name": "Senior Developer",
|
|
105
|
-
"category": "engineering",
|
|
106
|
-
"description": "Premium implementation specialist. Masters Laravel/Livewire/FluxUI, advanced CSS, Three.js.",
|
|
107
|
-
"tags": ["laravel", "livewire", "css", "threejs"],
|
|
108
|
-
"default_enabled": True,
|
|
109
|
-
"priority": 8
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
"id": "engineering-ai-engineer",
|
|
113
|
-
"name": "AI/ML Engineer",
|
|
114
|
-
"category": "engineering",
|
|
115
|
-
"description": "Machine learning model development, deployment, and integration into production systems.",
|
|
116
|
-
"tags": ["ml", "ai", "models", "data-pipelines"],
|
|
117
|
-
"default_enabled": True,
|
|
118
|
-
"priority": 7
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
"id": "Backend Architect",
|
|
122
|
-
"name": "Backend Architect",
|
|
123
|
-
"category": "engineering",
|
|
124
|
-
"description": "Scalable system design, database architecture, API development, cloud infrastructure.",
|
|
125
|
-
"tags": ["backend", "api", "database", "cloud"],
|
|
126
|
-
"default_enabled": True,
|
|
127
|
-
"priority": 8
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
"id": "Frontend Developer",
|
|
131
|
-
"name": "Frontend Developer",
|
|
132
|
-
"category": "engineering",
|
|
133
|
-
"description": "Modern web technologies, React/Vue/Angular frameworks, UI implementation.",
|
|
134
|
-
"tags": ["frontend", "react", "vue", "angular", "ui"],
|
|
135
|
-
"default_enabled": True,
|
|
136
|
-
"priority": 8
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
"id": "kotlin-material3-dev",
|
|
140
|
-
"name": "Kotlin Material3 Dev",
|
|
141
|
-
"category": "engineering",
|
|
142
|
-
"description": "Kotlin development with Material3 UI, color schemes, theming, and visual design.",
|
|
143
|
-
"tags": ["kotlin", "android", "material3", "mobile"],
|
|
144
|
-
"default_enabled": False,
|
|
145
|
-
"priority": 6
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
"id": "Mobile App Builder",
|
|
149
|
-
"name": "Mobile App Builder",
|
|
150
|
-
"category": "engineering",
|
|
151
|
-
"description": "Native iOS/Android development and cross-platform frameworks.",
|
|
152
|
-
"tags": ["mobile", "ios", "android", "react-native", "flutter"],
|
|
153
|
-
"default_enabled": False,
|
|
154
|
-
"priority": 6
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
"id": "Rapid Prototyper",
|
|
158
|
-
"name": "Rapid Prototyper",
|
|
159
|
-
"category": "engineering",
|
|
160
|
-
"description": "Ultra-fast proof-of-concept and MVP creation.",
|
|
161
|
-
"tags": ["prototype", "mvp", "fast", "poc"],
|
|
162
|
-
"default_enabled": True,
|
|
163
|
-
"priority": 7
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
"id": "LSP/Index Engineer",
|
|
167
|
-
"name": "LSP/Index Engineer",
|
|
168
|
-
"category": "engineering",
|
|
169
|
-
"description": "Language Server Protocol specialist for code intelligence systems.",
|
|
170
|
-
"tags": ["lsp", "indexing", "code-intelligence"],
|
|
171
|
-
"default_enabled": False,
|
|
172
|
-
"priority": 5
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
# Feature Development
|
|
176
|
-
{
|
|
177
|
-
"id": "feature-dev:code-architect",
|
|
178
|
-
"name": "Code Architect",
|
|
179
|
-
"category": "engineering",
|
|
180
|
-
"description": "Designs feature architectures by analyzing codebase patterns and conventions.",
|
|
181
|
-
"tags": ["architecture", "patterns", "design"],
|
|
182
|
-
"default_enabled": True,
|
|
183
|
-
"priority": 8
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
"id": "feature-dev:code-explorer",
|
|
187
|
-
"name": "Code Explorer",
|
|
188
|
-
"category": "engineering",
|
|
189
|
-
"description": "Deep analysis of existing features, execution paths, and dependencies.",
|
|
190
|
-
"tags": ["analysis", "tracing", "dependencies"],
|
|
191
|
-
"default_enabled": True,
|
|
192
|
-
"priority": 8
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
"id": "feature-dev:code-reviewer",
|
|
196
|
-
"name": "Code Reviewer",
|
|
197
|
-
"category": "engineering",
|
|
198
|
-
"description": "Reviews code for bugs, security vulnerabilities, and quality issues.",
|
|
199
|
-
"tags": ["review", "security", "quality"],
|
|
200
|
-
"default_enabled": True,
|
|
201
|
-
"priority": 8
|
|
202
|
-
},
|
|
203
|
-
|
|
204
|
-
# Testing & QA
|
|
205
|
-
{
|
|
206
|
-
"id": "testing-reality-checker",
|
|
207
|
-
"name": "Reality Checker",
|
|
208
|
-
"category": "testing",
|
|
209
|
-
"description": "Evidence-based certification. Requires overwhelming proof for production readiness.",
|
|
210
|
-
"tags": ["testing", "verification", "strict"],
|
|
211
|
-
"default_enabled": True,
|
|
212
|
-
"priority": 8
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
"id": "EvidenceQA",
|
|
216
|
-
"name": "Evidence QA",
|
|
217
|
-
"category": "testing",
|
|
218
|
-
"description": "Screenshot-obsessed QA specialist. Requires visual proof for everything.",
|
|
219
|
-
"tags": ["qa", "screenshots", "visual-testing"],
|
|
220
|
-
"default_enabled": True,
|
|
221
|
-
"priority": 7
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
"id": "API Tester",
|
|
225
|
-
"name": "API Tester",
|
|
226
|
-
"category": "testing",
|
|
227
|
-
"description": "Comprehensive API validation, performance testing, and quality assurance.",
|
|
228
|
-
"tags": ["api", "testing", "performance"],
|
|
229
|
-
"default_enabled": True,
|
|
230
|
-
"priority": 7
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
"id": "Test Results Analyzer",
|
|
234
|
-
"name": "Test Results Analyzer",
|
|
235
|
-
"category": "testing",
|
|
236
|
-
"description": "Test result evaluation, quality metrics analysis, and actionable insights.",
|
|
237
|
-
"tags": ["analysis", "metrics", "insights"],
|
|
238
|
-
"default_enabled": True,
|
|
239
|
-
"priority": 6
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
"id": "Performance Benchmarker",
|
|
243
|
-
"name": "Performance Benchmarker",
|
|
244
|
-
"category": "testing",
|
|
245
|
-
"description": "Performance testing and optimization across all applications.",
|
|
246
|
-
"tags": ["performance", "benchmarking", "optimization"],
|
|
247
|
-
"default_enabled": True,
|
|
248
|
-
"priority": 7
|
|
249
|
-
},
|
|
250
|
-
|
|
251
|
-
# Operations
|
|
252
|
-
{
|
|
253
|
-
"id": "DevOps Automator",
|
|
254
|
-
"name": "DevOps Automator",
|
|
255
|
-
"category": "operations",
|
|
256
|
-
"description": "Infrastructure automation, CI/CD pipeline development, and cloud operations.",
|
|
257
|
-
"tags": ["devops", "ci-cd", "automation", "cloud"],
|
|
258
|
-
"default_enabled": True,
|
|
259
|
-
"priority": 8
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
"id": "Infrastructure Maintainer",
|
|
263
|
-
"name": "Infrastructure Maintainer",
|
|
264
|
-
"category": "operations",
|
|
265
|
-
"description": "System reliability, performance optimization, and technical operations.",
|
|
266
|
-
"tags": ["infrastructure", "reliability", "maintenance"],
|
|
267
|
-
"default_enabled": True,
|
|
268
|
-
"priority": 7
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
"id": "Workflow Optimizer",
|
|
272
|
-
"name": "Workflow Optimizer",
|
|
273
|
-
"category": "operations",
|
|
274
|
-
"description": "Process improvement specialist for maximum productivity and efficiency.",
|
|
275
|
-
"tags": ["workflow", "optimization", "automation"],
|
|
276
|
-
"default_enabled": False,
|
|
277
|
-
"priority": 5
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
"id": "Tool Evaluator",
|
|
281
|
-
"name": "Tool Evaluator",
|
|
282
|
-
"category": "operations",
|
|
283
|
-
"description": "Technology assessment specialist for tools, software, and platforms.",
|
|
284
|
-
"tags": ["evaluation", "tools", "assessment"],
|
|
285
|
-
"default_enabled": False,
|
|
286
|
-
"priority": 5
|
|
287
|
-
},
|
|
288
|
-
|
|
289
|
-
# Design & UX
|
|
290
|
-
{
|
|
291
|
-
"id": "ArchitectUX",
|
|
292
|
-
"name": "Architect UX",
|
|
293
|
-
"category": "design",
|
|
294
|
-
"description": "Technical architecture and UX specialist with CSS systems expertise.",
|
|
295
|
-
"tags": ["ux", "architecture", "css"],
|
|
296
|
-
"default_enabled": True,
|
|
297
|
-
"priority": 8
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
"id": "UI Designer",
|
|
301
|
-
"name": "UI Designer",
|
|
302
|
-
"category": "design",
|
|
303
|
-
"description": "Visual design systems, component libraries, and pixel-perfect interfaces.",
|
|
304
|
-
"tags": ["ui", "design-systems", "components"],
|
|
305
|
-
"default_enabled": True,
|
|
306
|
-
"priority": 8
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
"id": "UX Researcher",
|
|
310
|
-
"name": "UX Researcher",
|
|
311
|
-
"category": "design",
|
|
312
|
-
"description": "User behavior analysis, usability testing, and data-driven design insights.",
|
|
313
|
-
"tags": ["research", "usability", "user-behavior"],
|
|
314
|
-
"default_enabled": True,
|
|
315
|
-
"priority": 7
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
"id": "Brand Guardian",
|
|
319
|
-
"name": "Brand Guardian",
|
|
320
|
-
"category": "design",
|
|
321
|
-
"description": "Brand identity development, consistency maintenance, and strategic positioning.",
|
|
322
|
-
"tags": ["brand", "identity", "consistency"],
|
|
323
|
-
"default_enabled": False,
|
|
324
|
-
"priority": 5
|
|
325
|
-
},
|
|
326
|
-
{
|
|
327
|
-
"id": "design-visual-storyteller",
|
|
328
|
-
"name": "Visual Storyteller",
|
|
329
|
-
"category": "design",
|
|
330
|
-
"description": "Visual narratives, multimedia content, and brand storytelling through design.",
|
|
331
|
-
"tags": ["storytelling", "multimedia", "visual"],
|
|
332
|
-
"default_enabled": False,
|
|
333
|
-
"priority": 5
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
"id": "Whimsy Injector",
|
|
337
|
-
"name": "Whimsy Injector",
|
|
338
|
-
"category": "design",
|
|
339
|
-
"description": "Adds personality, delight, and playful elements to brand experiences.",
|
|
340
|
-
"tags": ["whimsy", "delight", "personality"],
|
|
341
|
-
"default_enabled": False,
|
|
342
|
-
"priority": 4
|
|
343
|
-
},
|
|
344
|
-
|
|
345
|
-
# Product
|
|
346
|
-
{
|
|
347
|
-
"id": "project-manager-senior",
|
|
348
|
-
"name": "Senior Project Manager",
|
|
349
|
-
"category": "product",
|
|
350
|
-
"description": "Converts specs to tasks with realistic scope and exact requirements.",
|
|
351
|
-
"tags": ["project-management", "specs", "tasks"],
|
|
352
|
-
"default_enabled": True,
|
|
353
|
-
"priority": 8
|
|
354
|
-
},
|
|
355
|
-
{
|
|
356
|
-
"id": "product-sprint-prioritizer",
|
|
357
|
-
"name": "Sprint Prioritizer",
|
|
358
|
-
"category": "product",
|
|
359
|
-
"description": "Agile sprint planning, feature prioritization, and resource allocation.",
|
|
360
|
-
"tags": ["agile", "sprint", "prioritization"],
|
|
361
|
-
"default_enabled": True,
|
|
362
|
-
"priority": 7
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
"id": "product-feedback-synthesizer",
|
|
366
|
-
"name": "Feedback Synthesizer",
|
|
367
|
-
"category": "product",
|
|
368
|
-
"description": "Collects and analyzes user feedback to extract actionable product insights.",
|
|
369
|
-
"tags": ["feedback", "analysis", "insights"],
|
|
370
|
-
"default_enabled": False,
|
|
371
|
-
"priority": 5
|
|
372
|
-
},
|
|
373
|
-
{
|
|
374
|
-
"id": "product-trend-researcher",
|
|
375
|
-
"name": "Trend Researcher",
|
|
376
|
-
"category": "product",
|
|
377
|
-
"description": "Market intelligence, emerging trends, and competitive analysis.",
|
|
378
|
-
"tags": ["trends", "market", "competitive"],
|
|
379
|
-
"default_enabled": False,
|
|
380
|
-
"priority": 5
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
"id": "Studio Operations",
|
|
384
|
-
"name": "Studio Operations",
|
|
385
|
-
"category": "product",
|
|
386
|
-
"description": "Day-to-day studio efficiency, process optimization, and resource coordination.",
|
|
387
|
-
"tags": ["operations", "efficiency", "coordination"],
|
|
388
|
-
"default_enabled": False,
|
|
389
|
-
"priority": 4
|
|
390
|
-
},
|
|
391
|
-
{
|
|
392
|
-
"id": "Project Shepherd",
|
|
393
|
-
"name": "Project Shepherd",
|
|
394
|
-
"category": "product",
|
|
395
|
-
"description": "Cross-functional project coordination and stakeholder alignment.",
|
|
396
|
-
"tags": ["coordination", "cross-functional", "stakeholders"],
|
|
397
|
-
"default_enabled": False,
|
|
398
|
-
"priority": 5
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
"id": "Experiment Tracker",
|
|
402
|
-
"name": "Experiment Tracker",
|
|
403
|
-
"category": "product",
|
|
404
|
-
"description": "Experiment design, A/B testing, and hypothesis validation.",
|
|
405
|
-
"tags": ["experiments", "ab-testing", "validation"],
|
|
406
|
-
"default_enabled": False,
|
|
407
|
-
"priority": 5
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
"id": "Studio Producer",
|
|
411
|
-
"name": "Studio Producer",
|
|
412
|
-
"category": "product",
|
|
413
|
-
"description": "High-level creative and technical project orchestration.",
|
|
414
|
-
"tags": ["production", "creative", "orchestration"],
|
|
415
|
-
"default_enabled": False,
|
|
416
|
-
"priority": 5
|
|
417
|
-
},
|
|
418
|
-
|
|
419
|
-
# Marketing
|
|
420
|
-
{
|
|
421
|
-
"id": "marketing-growth-hacker",
|
|
422
|
-
"name": "Growth Hacker",
|
|
423
|
-
"category": "marketing",
|
|
424
|
-
"description": "Rapid user acquisition through data-driven experimentation and viral loops.",
|
|
425
|
-
"tags": ["growth", "acquisition", "viral"],
|
|
426
|
-
"default_enabled": False,
|
|
427
|
-
"priority": 6
|
|
428
|
-
},
|
|
429
|
-
{
|
|
430
|
-
"id": "marketing-content-creator",
|
|
431
|
-
"name": "Content Creator",
|
|
432
|
-
"category": "marketing",
|
|
433
|
-
"description": "Multi-platform campaigns, editorial calendars, and brand storytelling.",
|
|
434
|
-
"tags": ["content", "campaigns", "storytelling"],
|
|
435
|
-
"default_enabled": False,
|
|
436
|
-
"priority": 5
|
|
437
|
-
},
|
|
438
|
-
{
|
|
439
|
-
"id": "marketing-social-media-strategist",
|
|
440
|
-
"name": "Social Media Strategist",
|
|
441
|
-
"category": "marketing",
|
|
442
|
-
"description": "Twitter, LinkedIn strategies with viral campaigns and thought leadership.",
|
|
443
|
-
"tags": ["social-media", "linkedin", "twitter"],
|
|
444
|
-
"default_enabled": False,
|
|
445
|
-
"priority": 5
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
"id": "marketing-instagram-curator",
|
|
449
|
-
"name": "Instagram Curator",
|
|
450
|
-
"category": "marketing",
|
|
451
|
-
"description": "Visual storytelling, community building, and multi-format content for Instagram.",
|
|
452
|
-
"tags": ["instagram", "visual", "community"],
|
|
453
|
-
"default_enabled": False,
|
|
454
|
-
"priority": 4
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
"id": "marketing-tiktok-strategist",
|
|
458
|
-
"name": "TikTok Strategist",
|
|
459
|
-
"category": "marketing",
|
|
460
|
-
"description": "Viral content creation, algorithm optimization, and TikTok community building.",
|
|
461
|
-
"tags": ["tiktok", "viral", "algorithm"],
|
|
462
|
-
"default_enabled": False,
|
|
463
|
-
"priority": 4
|
|
464
|
-
},
|
|
465
|
-
{
|
|
466
|
-
"id": "marketing-twitter-engager",
|
|
467
|
-
"name": "Twitter Engager",
|
|
468
|
-
"category": "marketing",
|
|
469
|
-
"description": "Real-time engagement, thought leadership, and community-driven growth.",
|
|
470
|
-
"tags": ["twitter", "engagement", "thought-leadership"],
|
|
471
|
-
"default_enabled": False,
|
|
472
|
-
"priority": 4
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
"id": "marketing-reddit-community-builder",
|
|
476
|
-
"name": "Reddit Community Builder",
|
|
477
|
-
"category": "marketing",
|
|
478
|
-
"description": "Authentic Reddit engagement, value-driven content, and community building.",
|
|
479
|
-
"tags": ["reddit", "community", "authentic"],
|
|
480
|
-
"default_enabled": False,
|
|
481
|
-
"priority": 4
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
"id": "App Store Optimizer",
|
|
485
|
-
"name": "App Store Optimizer",
|
|
486
|
-
"category": "marketing",
|
|
487
|
-
"description": "ASO, conversion rate optimization, and app discoverability.",
|
|
488
|
-
"tags": ["aso", "app-store", "conversion"],
|
|
489
|
-
"default_enabled": False,
|
|
490
|
-
"priority": 4
|
|
491
|
-
},
|
|
492
|
-
|
|
493
|
-
# Data & Analytics
|
|
494
|
-
{
|
|
495
|
-
"id": "data-analytics-reporter",
|
|
496
|
-
"name": "Analytics Reporter",
|
|
497
|
-
"category": "data",
|
|
498
|
-
"description": "Transforms raw data into actionable business insights and dashboards.",
|
|
499
|
-
"tags": ["analytics", "dashboards", "insights"],
|
|
500
|
-
"default_enabled": True,
|
|
501
|
-
"priority": 7
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
"id": "Analytics Reporter",
|
|
505
|
-
"name": "Analytics Reporter",
|
|
506
|
-
"category": "data",
|
|
507
|
-
"description": "Data analysis, KPI tracking, and strategic decision support.",
|
|
508
|
-
"tags": ["analytics", "kpi", "reporting"],
|
|
509
|
-
"default_enabled": True,
|
|
510
|
-
"priority": 7
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
"id": "Finance Tracker",
|
|
514
|
-
"name": "Finance Tracker",
|
|
515
|
-
"category": "data",
|
|
516
|
-
"description": "Financial planning, budget management, and performance analysis.",
|
|
517
|
-
"tags": ["finance", "budget", "planning"],
|
|
518
|
-
"default_enabled": False,
|
|
519
|
-
"priority": 5
|
|
520
|
-
},
|
|
521
|
-
{
|
|
522
|
-
"id": "Executive Summary Generator",
|
|
523
|
-
"name": "Executive Summary Generator",
|
|
524
|
-
"category": "data",
|
|
525
|
-
"description": "McKinsey-style executive summaries with SCQA and Pyramid Principle frameworks.",
|
|
526
|
-
"tags": ["executive", "summary", "frameworks"],
|
|
527
|
-
"default_enabled": False,
|
|
528
|
-
"priority": 5
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
"id": "Legal Compliance Checker",
|
|
532
|
-
"name": "Legal Compliance Checker",
|
|
533
|
-
"category": "data",
|
|
534
|
-
"description": "Ensures compliance with laws, regulations, and industry standards.",
|
|
535
|
-
"tags": ["legal", "compliance", "regulations"],
|
|
536
|
-
"default_enabled": False,
|
|
537
|
-
"priority": 4
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
"id": "Support Responder",
|
|
541
|
-
"name": "Support Responder",
|
|
542
|
-
"category": "data",
|
|
543
|
-
"description": "Customer support, issue resolution, and multi-channel service.",
|
|
544
|
-
"tags": ["support", "customer-service", "issues"],
|
|
545
|
-
"default_enabled": False,
|
|
546
|
-
"priority": 4
|
|
547
|
-
},
|
|
548
|
-
|
|
549
|
-
# XR & Spatial
|
|
550
|
-
{
|
|
551
|
-
"id": "XR Interface Architect",
|
|
552
|
-
"name": "XR Interface Architect",
|
|
553
|
-
"category": "xr",
|
|
554
|
-
"description": "Spatial interaction design for immersive AR/VR/XR environments.",
|
|
555
|
-
"tags": ["xr", "spatial", "interaction"],
|
|
556
|
-
"default_enabled": False,
|
|
557
|
-
"priority": 6
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
"id": "XR Immersive Developer",
|
|
561
|
-
"name": "XR Immersive Developer",
|
|
562
|
-
"category": "xr",
|
|
563
|
-
"description": "WebXR and browser-based AR/VR/XR applications.",
|
|
564
|
-
"tags": ["webxr", "browser", "immersive"],
|
|
565
|
-
"default_enabled": False,
|
|
566
|
-
"priority": 6
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
"id": "XR Cockpit Interaction Specialist",
|
|
570
|
-
"name": "XR Cockpit Specialist",
|
|
571
|
-
"category": "xr",
|
|
572
|
-
"description": "Cockpit-based control systems for XR environments.",
|
|
573
|
-
"tags": ["cockpit", "controls", "xr"],
|
|
574
|
-
"default_enabled": False,
|
|
575
|
-
"priority": 5
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
"id": "visionos-spatial-engineer",
|
|
579
|
-
"name": "VisionOS Spatial Engineer",
|
|
580
|
-
"category": "xr",
|
|
581
|
-
"description": "Native visionOS spatial computing with SwiftUI and Liquid Glass design.",
|
|
582
|
-
"tags": ["visionos", "swiftui", "spatial"],
|
|
583
|
-
"default_enabled": False,
|
|
584
|
-
"priority": 6
|
|
585
|
-
},
|
|
586
|
-
{
|
|
587
|
-
"id": "terminal-integration-specialist",
|
|
588
|
-
"name": "Terminal Integration Specialist",
|
|
589
|
-
"category": "xr",
|
|
590
|
-
"description": "Terminal emulation, SwiftTerm integration, and VT100/xterm standards.",
|
|
591
|
-
"tags": ["terminal", "swiftterm", "integration"],
|
|
592
|
-
"default_enabled": False,
|
|
593
|
-
"priority": 5
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
"id": "macOS Spatial/Metal Engineer",
|
|
597
|
-
"name": "macOS Metal Engineer",
|
|
598
|
-
"category": "xr",
|
|
599
|
-
"description": "Native Swift and Metal for high-performance 3D rendering on macOS and Vision Pro.",
|
|
600
|
-
"tags": ["metal", "swift", "3d", "macos"],
|
|
601
|
-
"default_enabled": False,
|
|
602
|
-
"priority": 6
|
|
603
|
-
},
|
|
604
|
-
|
|
605
|
-
# Special
|
|
606
|
-
{
|
|
607
|
-
"id": "agents-orchestrator",
|
|
608
|
-
"name": "Agents Orchestrator",
|
|
609
|
-
"category": "operations",
|
|
610
|
-
"description": "Autonomous pipeline manager that orchestrates the entire development workflow.",
|
|
611
|
-
"tags": ["orchestration", "pipeline", "automation"],
|
|
612
|
-
"default_enabled": True,
|
|
613
|
-
"priority": 9
|
|
614
|
-
},
|
|
615
|
-
{
|
|
616
|
-
"id": "claude-code-guide",
|
|
617
|
-
"name": "Claude Code Guide",
|
|
618
|
-
"category": "exploration",
|
|
619
|
-
"description": "Expert on Claude Code features, hooks, MCP servers, settings, and integrations.",
|
|
620
|
-
"tags": ["claude-code", "help", "guide"],
|
|
621
|
-
"default_enabled": True,
|
|
622
|
-
"priority": 8
|
|
623
|
-
}
|
|
624
|
-
]
|
|
625
|
-
|
|
626
|
-
# MCP Servers
|
|
627
|
-
AVAILABLE_MCPS = [
|
|
628
|
-
{
|
|
629
|
-
"id": "claude-memory",
|
|
630
|
-
"name": "Claude Memory",
|
|
631
|
-
"description": "Semantic memory storage and retrieval for persistent context.",
|
|
632
|
-
"icon": "brain",
|
|
633
|
-
"color": "#a371f7",
|
|
634
|
-
"default_enabled": True
|
|
635
|
-
},
|
|
636
|
-
{
|
|
637
|
-
"id": "context7",
|
|
638
|
-
"name": "Context7",
|
|
639
|
-
"description": "Up-to-date documentation and API references from the web.",
|
|
640
|
-
"icon": "book",
|
|
641
|
-
"color": "#58a6ff",
|
|
642
|
-
"default_enabled": True
|
|
643
|
-
},
|
|
644
|
-
{
|
|
645
|
-
"id": "filesystem",
|
|
646
|
-
"name": "Filesystem",
|
|
647
|
-
"description": "Enhanced file system operations and management.",
|
|
648
|
-
"icon": "folder",
|
|
649
|
-
"color": "#d29922",
|
|
650
|
-
"default_enabled": False
|
|
651
|
-
},
|
|
652
|
-
{
|
|
653
|
-
"id": "github",
|
|
654
|
-
"name": "GitHub",
|
|
655
|
-
"description": "GitHub API integration for repos, issues, and PRs.",
|
|
656
|
-
"icon": "github",
|
|
657
|
-
"color": "#8b949e",
|
|
658
|
-
"default_enabled": False
|
|
659
|
-
},
|
|
660
|
-
{
|
|
661
|
-
"id": "postgres",
|
|
662
|
-
"name": "PostgreSQL",
|
|
663
|
-
"description": "Direct PostgreSQL database access and queries.",
|
|
664
|
-
"icon": "database",
|
|
665
|
-
"color": "#336791",
|
|
666
|
-
"default_enabled": False
|
|
667
|
-
},
|
|
668
|
-
{
|
|
669
|
-
"id": "puppeteer",
|
|
670
|
-
"name": "Puppeteer",
|
|
671
|
-
"description": "Browser automation and web scraping capabilities.",
|
|
672
|
-
"icon": "globe",
|
|
673
|
-
"color": "#3fb950",
|
|
674
|
-
"default_enabled": False
|
|
675
|
-
}
|
|
676
|
-
]
|
|
677
|
-
|
|
678
|
-
# Hooks
|
|
679
|
-
AVAILABLE_HOOKS = [
|
|
680
|
-
{
|
|
681
|
-
"id": "grounding-hook",
|
|
682
|
-
"name": "Grounding Hook",
|
|
683
|
-
"description": "Injects context and anchors before every response to prevent hallucinations.",
|
|
684
|
-
"trigger": "UserPromptSubmit",
|
|
685
|
-
"icon": "anchor",
|
|
686
|
-
"color": "#a371f7",
|
|
687
|
-
"default_enabled": True
|
|
688
|
-
},
|
|
689
|
-
{
|
|
690
|
-
"id": "pre-tool-check",
|
|
691
|
-
"name": "Pre-Tool Check",
|
|
692
|
-
"description": "Blocks actions that violate anchors or entity registry BEFORE execution.",
|
|
693
|
-
"trigger": "PreToolUse",
|
|
694
|
-
"icon": "shield",
|
|
695
|
-
"color": "#d29922",
|
|
696
|
-
"default_enabled": True
|
|
697
|
-
},
|
|
698
|
-
{
|
|
699
|
-
"id": "detect-correction",
|
|
700
|
-
"name": "Detect Correction",
|
|
701
|
-
"description": "Auto-detects when user corrects Claude and creates anchors.",
|
|
702
|
-
"trigger": "UserPromptSubmit",
|
|
703
|
-
"icon": "check-circle",
|
|
704
|
-
"color": "#3fb950",
|
|
705
|
-
"default_enabled": True
|
|
706
|
-
},
|
|
707
|
-
{
|
|
708
|
-
"id": "log-tool-use",
|
|
709
|
-
"name": "Log Tool Use",
|
|
710
|
-
"description": "Logs all tool usage to the timeline for tracking.",
|
|
711
|
-
"trigger": "PostToolUse",
|
|
712
|
-
"icon": "file-text",
|
|
713
|
-
"color": "#58a6ff",
|
|
714
|
-
"default_enabled": True
|
|
715
|
-
},
|
|
716
|
-
{
|
|
717
|
-
"id": "auto-detect-response",
|
|
718
|
-
"name": "Auto-Detect Response",
|
|
719
|
-
"description": "Extracts decisions and observations from Claude's responses using LLM.",
|
|
720
|
-
"trigger": "Stop",
|
|
721
|
-
"icon": "brain",
|
|
722
|
-
"color": "#f85149",
|
|
723
|
-
"default_enabled": True
|
|
724
|
-
},
|
|
725
|
-
{
|
|
726
|
-
"id": "log-user-request",
|
|
727
|
-
"name": "Log User Request",
|
|
728
|
-
"description": "Logs user requests to the timeline.",
|
|
729
|
-
"trigger": "UserPromptSubmit",
|
|
730
|
-
"icon": "message-circle",
|
|
731
|
-
"color": "#8b949e",
|
|
732
|
-
"default_enabled": True
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import List, Dict, Any, Optional
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Paths to Claude Code settings files
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
_HOME = Path.home()
|
|
20
|
+
_GLOBAL_SETTINGS_PATH = _HOME / ".claude" / "settings.json"
|
|
21
|
+
|
|
22
|
+
# Project root is two levels up from this file:
|
|
23
|
+
# memory-agent/services/agent_registry.py -> memory-agent -> project root
|
|
24
|
+
_PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
|
|
25
|
+
_LOCAL_SETTINGS_PATH = _PROJECT_ROOT / ".claude" / "settings.local.json"
|
|
26
|
+
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
# Load static catalog from JSON
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
_CATALOG_PATH = Path(__file__).resolve().parent / "agent_catalog.json"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _load_catalog() -> dict:
|
|
34
|
+
"""Load the agent catalog from JSON file."""
|
|
35
|
+
try:
|
|
36
|
+
with open(_CATALOG_PATH, "r", encoding="utf-8") as f:
|
|
37
|
+
return json.load(f)
|
|
38
|
+
except Exception as e:
|
|
39
|
+
logger.error(f"Failed to load agent catalog from {_CATALOG_PATH}: {e}")
|
|
40
|
+
return {"categories": {}, "agents": [], "mcps": [], "hooks": []}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
_catalog = _load_catalog()
|
|
44
|
+
|
|
45
|
+
AGENT_CATEGORIES = _catalog.get("categories", {})
|
|
46
|
+
AVAILABLE_AGENTS = _catalog.get("agents", [])
|
|
47
|
+
AVAILABLE_MCPS = _catalog.get("mcps", [])
|
|
48
|
+
AVAILABLE_HOOKS = _catalog.get("hooks", [])
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
# Helper: derive a hook ID from its command string
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
def _hook_id_from_command(command: str) -> str:
|
|
55
|
+
"""Extract a stable identifier from a hook command path."""
|
|
56
|
+
basename = Path(command.split()[-1]).stem
|
|
57
|
+
return basename.replace("_", "-")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# ---------------------------------------------------------------------------
|
|
61
|
+
# Dynamic loader: read configured hooks from settings files
|
|
62
|
+
# ---------------------------------------------------------------------------
|
|
63
|
+
def _read_json_safe(path: Path) -> dict:
|
|
64
|
+
"""Read a JSON file, returning empty dict on any error."""
|
|
65
|
+
try:
|
|
66
|
+
if path.exists():
|
|
67
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
68
|
+
return json.load(f)
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.warning(f"Could not read {path}: {e}")
|
|
71
|
+
return {}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _extract_hooks_from_settings(data: dict) -> Dict[str, Dict[str, Any]]:
|
|
75
|
+
"""Parse the 'hooks' section of a Claude Code settings file.
|
|
76
|
+
|
|
77
|
+
Returns a dict keyed by hook-id with trigger, matcher, and command.
|
|
78
|
+
"""
|
|
79
|
+
result: Dict[str, Dict[str, Any]] = {}
|
|
80
|
+
hooks_section = data.get("hooks", {})
|
|
81
|
+
|
|
82
|
+
_trigger_suffix = {
|
|
83
|
+
"PostToolUse": "-post",
|
|
84
|
+
"PreToolUse": "-pre",
|
|
85
|
+
"PreCompact": "-compact",
|
|
86
|
+
"SessionEnd": "-sessionend",
|
|
733
87
|
}
|
|
734
|
-
]
|
|
735
88
|
|
|
89
|
+
for trigger, entries in hooks_section.items():
|
|
90
|
+
if not isinstance(entries, list):
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
for entry in entries:
|
|
94
|
+
matcher = entry.get("matcher", "")
|
|
95
|
+
hook_items = entry.get("hooks", [entry])
|
|
96
|
+
for item in hook_items:
|
|
97
|
+
if item.get("type") != "command":
|
|
98
|
+
continue
|
|
99
|
+
command = item.get("command", "")
|
|
100
|
+
if not command:
|
|
101
|
+
continue
|
|
102
|
+
hook_id = _hook_id_from_command(command)
|
|
103
|
+
|
|
104
|
+
if hook_id in result and result[hook_id]["trigger"] != trigger:
|
|
105
|
+
suffix = _trigger_suffix.get(trigger, f"-{trigger.lower()}")
|
|
106
|
+
hook_id = hook_id + suffix
|
|
107
|
+
|
|
108
|
+
result[hook_id] = {
|
|
109
|
+
"trigger": trigger,
|
|
110
|
+
"matcher": matcher,
|
|
111
|
+
"command": command
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return result
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _extract_mcps_from_settings(data: dict) -> Dict[str, Dict[str, Any]]:
|
|
118
|
+
"""Parse the 'mcpServers' section of a Claude Code settings file."""
|
|
119
|
+
result: Dict[str, Dict[str, Any]] = {}
|
|
120
|
+
mcp_section = data.get("mcpServers", {})
|
|
121
|
+
|
|
122
|
+
for server_id, config in mcp_section.items():
|
|
123
|
+
if isinstance(config, dict):
|
|
124
|
+
result[server_id] = {
|
|
125
|
+
"command": config.get("command", ""),
|
|
126
|
+
"args": config.get("args", []),
|
|
127
|
+
"env": config.get("env", {})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def load_configured_hooks(
|
|
134
|
+
project_root: Optional[str] = None
|
|
135
|
+
) -> List[Dict[str, Any]]:
|
|
136
|
+
"""Load hooks with live configured status from settings files."""
|
|
137
|
+
global_data = _read_json_safe(_GLOBAL_SETTINGS_PATH)
|
|
138
|
+
local_path = (
|
|
139
|
+
Path(project_root) / ".claude" / "settings.local.json"
|
|
140
|
+
if project_root
|
|
141
|
+
else _LOCAL_SETTINGS_PATH
|
|
142
|
+
)
|
|
143
|
+
local_data = _read_json_safe(local_path)
|
|
144
|
+
|
|
145
|
+
global_hooks = _extract_hooks_from_settings(global_data)
|
|
146
|
+
local_hooks = _extract_hooks_from_settings(local_data)
|
|
147
|
+
|
|
148
|
+
enriched: List[Dict[str, Any]] = []
|
|
149
|
+
seen_ids: set = set()
|
|
150
|
+
|
|
151
|
+
for hook in AVAILABLE_HOOKS:
|
|
152
|
+
hook_copy = dict(hook)
|
|
153
|
+
hook_id = hook_copy["id"]
|
|
154
|
+
seen_ids.add(hook_id)
|
|
155
|
+
|
|
156
|
+
if hook_id in local_hooks:
|
|
157
|
+
hook_copy["configured"] = True
|
|
158
|
+
hook_copy["settings_source"] = "project"
|
|
159
|
+
hook_copy["command"] = local_hooks[hook_id].get("command", "")
|
|
160
|
+
elif hook_id in global_hooks:
|
|
161
|
+
hook_copy["configured"] = True
|
|
162
|
+
hook_copy["settings_source"] = "global"
|
|
163
|
+
hook_copy["command"] = global_hooks[hook_id].get("command", "")
|
|
164
|
+
else:
|
|
165
|
+
hook_copy["configured"] = False
|
|
166
|
+
hook_copy["settings_source"] = None
|
|
167
|
+
hook_copy["command"] = ""
|
|
168
|
+
|
|
169
|
+
enriched.append(hook_copy)
|
|
170
|
+
|
|
171
|
+
# Append hooks from settings not in the static catalog
|
|
172
|
+
for hook_id, info in {**global_hooks, **local_hooks}.items():
|
|
173
|
+
if hook_id in seen_ids:
|
|
174
|
+
continue
|
|
175
|
+
source = "project" if hook_id in local_hooks else "global"
|
|
176
|
+
enriched.append({
|
|
177
|
+
"id": hook_id,
|
|
178
|
+
"name": hook_id.replace("-", " ").replace("_", " ").title(),
|
|
179
|
+
"description": f"Discovered hook from {source} settings.",
|
|
180
|
+
"trigger": info.get("trigger", "Unknown"),
|
|
181
|
+
"matcher": info.get("matcher", ""),
|
|
182
|
+
"icon": "cpu",
|
|
183
|
+
"color": "#8b949e",
|
|
184
|
+
"default_enabled": True,
|
|
185
|
+
"source": source,
|
|
186
|
+
"configured": True,
|
|
187
|
+
"settings_source": source,
|
|
188
|
+
"command": info.get("command", "")
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
return enriched
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def load_configured_mcps(
|
|
195
|
+
project_root: Optional[str] = None
|
|
196
|
+
) -> List[Dict[str, Any]]:
|
|
197
|
+
"""Load MCP servers with live configured status from settings files."""
|
|
198
|
+
global_data = _read_json_safe(_GLOBAL_SETTINGS_PATH)
|
|
199
|
+
local_path = (
|
|
200
|
+
Path(project_root) / ".claude" / "settings.local.json"
|
|
201
|
+
if project_root
|
|
202
|
+
else _LOCAL_SETTINGS_PATH
|
|
203
|
+
)
|
|
204
|
+
local_data = _read_json_safe(local_path)
|
|
205
|
+
|
|
206
|
+
global_mcps = _extract_mcps_from_settings(global_data)
|
|
207
|
+
local_mcps = _extract_mcps_from_settings(local_data)
|
|
208
|
+
|
|
209
|
+
enriched: List[Dict[str, Any]] = []
|
|
210
|
+
seen_ids: set = set()
|
|
211
|
+
|
|
212
|
+
for mcp in AVAILABLE_MCPS:
|
|
213
|
+
mcp_copy = dict(mcp)
|
|
214
|
+
mcp_id = mcp_copy["id"]
|
|
215
|
+
seen_ids.add(mcp_id)
|
|
216
|
+
|
|
217
|
+
if mcp_id in local_mcps:
|
|
218
|
+
mcp_copy["configured"] = True
|
|
219
|
+
mcp_copy["settings_source"] = "project"
|
|
220
|
+
elif mcp_id in global_mcps:
|
|
221
|
+
mcp_copy["configured"] = True
|
|
222
|
+
mcp_copy["settings_source"] = "global"
|
|
223
|
+
else:
|
|
224
|
+
mcp_copy["configured"] = False
|
|
225
|
+
mcp_copy["settings_source"] = None
|
|
226
|
+
|
|
227
|
+
enriched.append(mcp_copy)
|
|
228
|
+
|
|
229
|
+
for mcp_id, info in {**global_mcps, **local_mcps}.items():
|
|
230
|
+
if mcp_id in seen_ids:
|
|
231
|
+
continue
|
|
232
|
+
source = "project" if mcp_id in local_mcps else "global"
|
|
233
|
+
enriched.append({
|
|
234
|
+
"id": mcp_id,
|
|
235
|
+
"name": mcp_id.replace("-", " ").replace("_", " ").title(),
|
|
236
|
+
"description": f"Discovered MCP server from {source} settings.",
|
|
237
|
+
"icon": "box",
|
|
238
|
+
"color": "#8b949e",
|
|
239
|
+
"default_enabled": True,
|
|
240
|
+
"source": source,
|
|
241
|
+
"configured": True,
|
|
242
|
+
"settings_source": source
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
return enriched
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# ---------------------------------------------------------------------------
|
|
249
|
+
# Helper functions (unchanged interface)
|
|
250
|
+
# ---------------------------------------------------------------------------
|
|
736
251
|
|
|
737
252
|
def get_agents_by_category():
|
|
738
253
|
"""Group agents by category."""
|