claude-self-reflect 3.3.0 → 4.0.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/.claude/agents/claude-self-reflect-test.md +525 -11
- package/.claude/agents/quality-fixer.md +314 -0
- package/.claude/agents/reflection-specialist.md +40 -1
- package/installer/cli.js +16 -0
- package/installer/postinstall.js +14 -0
- package/installer/statusline-setup.js +289 -0
- package/mcp-server/run-mcp.sh +45 -7
- package/mcp-server/src/code_reload_tool.py +271 -0
- package/mcp-server/src/embedding_manager.py +60 -26
- package/mcp-server/src/enhanced_tool_registry.py +407 -0
- package/mcp-server/src/mode_switch_tool.py +181 -0
- package/mcp-server/src/parallel_search.py +24 -85
- package/mcp-server/src/project_resolver.py +20 -2
- package/mcp-server/src/reflection_tools.py +60 -13
- package/mcp-server/src/rich_formatting.py +103 -0
- package/mcp-server/src/search_tools.py +180 -79
- package/mcp-server/src/security_patches.py +555 -0
- package/mcp-server/src/server.py +318 -240
- package/mcp-server/src/status.py +13 -8
- package/mcp-server/src/temporal_tools.py +10 -3
- package/mcp-server/src/test_quality.py +153 -0
- package/package.json +6 -1
- package/scripts/ast_grep_final_analyzer.py +328 -0
- package/scripts/ast_grep_unified_registry.py +710 -0
- package/scripts/csr-status +511 -0
- package/scripts/import-conversations-unified.py +114 -28
- package/scripts/session_quality_tracker.py +661 -0
- package/scripts/streaming-watcher.py +140 -5
- package/scripts/update_patterns.py +334 -0
|
@@ -50,38 +50,60 @@ class EmbeddingManager:
|
|
|
50
50
|
logger.warning(f"Error cleaning locks: {e}")
|
|
51
51
|
|
|
52
52
|
def initialize(self) -> bool:
|
|
53
|
-
"""Initialize
|
|
54
|
-
logger.info("Initializing embedding manager
|
|
53
|
+
"""Initialize embedding models based on configuration."""
|
|
54
|
+
logger.info("Initializing embedding manager...")
|
|
55
55
|
|
|
56
56
|
# Clean up any stale locks first
|
|
57
57
|
self._clean_stale_locks()
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
local_success = self._try_initialize_local()
|
|
59
|
+
local_success = False
|
|
61
60
|
voyage_success = False
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
# Only initialize models we actually need
|
|
63
|
+
if not self.prefer_local and self.voyage_key:
|
|
64
|
+
# Cloud mode: Skip local initialization to avoid error messages
|
|
65
|
+
logger.info("Cloud mode requested, skipping local model initialization")
|
|
64
66
|
voyage_success = self._try_initialize_voyage()
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
self.model_type = 'local'
|
|
75
|
-
logger.info("Default model set to LOCAL embeddings (fallback)")
|
|
67
|
+
if voyage_success:
|
|
68
|
+
self.model_type = 'voyage'
|
|
69
|
+
logger.info("Using VOYAGE embeddings (1024 dimensions)")
|
|
70
|
+
else:
|
|
71
|
+
# Fallback to local if voyage fails
|
|
72
|
+
logger.warning("Voyage initialization failed, falling back to local")
|
|
73
|
+
local_success = self._try_initialize_local()
|
|
74
|
+
if local_success:
|
|
75
|
+
self.model_type = 'local'
|
|
76
76
|
else:
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
# Local mode or mixed mode support
|
|
78
|
+
local_success = self._try_initialize_local()
|
|
79
|
+
|
|
80
|
+
# Only initialize voyage if NOT preferring local
|
|
81
|
+
if self.voyage_key and not self.prefer_local:
|
|
82
|
+
voyage_success = self._try_initialize_voyage()
|
|
83
|
+
|
|
84
|
+
# Set default model type - prefer_local takes priority
|
|
85
|
+
if self.prefer_local and local_success:
|
|
86
|
+
self.model_type = 'local'
|
|
87
|
+
logger.info("Using LOCAL embeddings (384 dimensions) - preferred")
|
|
88
|
+
elif voyage_success:
|
|
89
|
+
self.model_type = 'voyage'
|
|
90
|
+
logger.info("Using VOYAGE embeddings (1024 dimensions)")
|
|
91
|
+
elif local_success:
|
|
92
|
+
self.model_type = 'local'
|
|
93
|
+
logger.info("Using LOCAL embeddings (fallback)")
|
|
94
|
+
else:
|
|
95
|
+
logger.error("Failed to initialize any embedding model")
|
|
96
|
+
return False
|
|
79
97
|
|
|
80
98
|
logger.info(f"Embedding models available - Local: {local_success}, Voyage: {voyage_success}")
|
|
81
99
|
return True
|
|
82
100
|
|
|
83
101
|
def _try_initialize_local(self) -> bool:
|
|
84
102
|
"""Try to initialize local FastEmbed model with timeout and optimizations."""
|
|
103
|
+
return self.try_initialize_local()
|
|
104
|
+
|
|
105
|
+
def try_initialize_local(self) -> bool:
|
|
106
|
+
"""Public method to initialize local FastEmbed model with timeout and optimizations."""
|
|
85
107
|
try:
|
|
86
108
|
logger.info(f"Attempting to load local model: {self.embedding_model}")
|
|
87
109
|
|
|
@@ -137,16 +159,24 @@ class EmbeddingManager:
|
|
|
137
159
|
error = e
|
|
138
160
|
logger.error(f"Failed to initialize local model: {e}")
|
|
139
161
|
|
|
140
|
-
#
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
162
|
+
# SECURITY FIX: Use ThreadPoolExecutor with proper timeout handling
|
|
163
|
+
from concurrent.futures import ThreadPoolExecutor, TimeoutError as FuturesTimeoutError
|
|
164
|
+
|
|
165
|
+
# Create executor and manage lifecycle explicitly to avoid blocking on timeout
|
|
166
|
+
executor = ThreadPoolExecutor(max_workers=1)
|
|
167
|
+
future = executor.submit(init_model)
|
|
168
|
+
try:
|
|
169
|
+
future.result(timeout=self.download_timeout)
|
|
170
|
+
executor.shutdown(wait=True)
|
|
171
|
+
except FuturesTimeoutError:
|
|
147
172
|
logger.error(f"Model initialization timed out after {self.download_timeout}s")
|
|
148
173
|
logger.info("Tip: Set FASTEMBED_SKIP_HUGGINGFACE=true to use alternative download sources")
|
|
149
|
-
#
|
|
174
|
+
# Don't wait for the hung task
|
|
175
|
+
executor.shutdown(wait=False)
|
|
176
|
+
return False
|
|
177
|
+
except Exception as e:
|
|
178
|
+
logger.error(f"Model initialization failed: {e}")
|
|
179
|
+
executor.shutdown(wait=True)
|
|
150
180
|
return False
|
|
151
181
|
|
|
152
182
|
return success
|
|
@@ -160,6 +190,10 @@ class EmbeddingManager:
|
|
|
160
190
|
|
|
161
191
|
def _try_initialize_voyage(self) -> bool:
|
|
162
192
|
"""Try to initialize Voyage AI client."""
|
|
193
|
+
return self.try_initialize_voyage()
|
|
194
|
+
|
|
195
|
+
def try_initialize_voyage(self) -> bool:
|
|
196
|
+
"""Public method to initialize Voyage AI client."""
|
|
163
197
|
try:
|
|
164
198
|
logger.info("Attempting to initialize Voyage AI...")
|
|
165
199
|
import voyageai
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"""Enhanced tool registry with improved descriptions for better tool selection.
|
|
2
|
+
|
|
3
|
+
This module provides enhanced tool registration with:
|
|
4
|
+
1. csr_ namespace prefix for all tools
|
|
5
|
+
2. Explicit "when to use" guidance in descriptions
|
|
6
|
+
3. Response format flexibility (concise/detailed)
|
|
7
|
+
4. Better tool grouping and discoverability
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Optional, List, Literal
|
|
11
|
+
from fastmcp import Context
|
|
12
|
+
from pydantic import Field
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def register_enhanced_search_tools(mcp, tools):
|
|
16
|
+
"""Register search tools with enhanced descriptions for better selection rates."""
|
|
17
|
+
|
|
18
|
+
# Primary search tool - most commonly needed
|
|
19
|
+
@mcp.tool(name="csr_reflect_on_past")
|
|
20
|
+
async def csr_reflect_on_past(
|
|
21
|
+
ctx: Context,
|
|
22
|
+
query: str = Field(
|
|
23
|
+
description="The search query to find semantically similar conversations"
|
|
24
|
+
),
|
|
25
|
+
limit: int = Field(
|
|
26
|
+
default=5,
|
|
27
|
+
description="Maximum number of results to return"
|
|
28
|
+
),
|
|
29
|
+
min_score: float = Field(
|
|
30
|
+
default=0.3,
|
|
31
|
+
description="Minimum similarity score (0-1)"
|
|
32
|
+
),
|
|
33
|
+
use_decay: int = Field(
|
|
34
|
+
default=-1,
|
|
35
|
+
description="Apply time-based decay: 1=enable, 0=disable, -1=use environment default"
|
|
36
|
+
),
|
|
37
|
+
project: Optional[str] = Field(
|
|
38
|
+
default=None,
|
|
39
|
+
description="Search specific project only. Use 'all' to search across all projects"
|
|
40
|
+
),
|
|
41
|
+
mode: str = Field(
|
|
42
|
+
default="full",
|
|
43
|
+
description="Search mode: 'full' (all results), 'quick' (count only), 'summary' (insights)"
|
|
44
|
+
),
|
|
45
|
+
response_format: Literal["concise", "detailed", "xml"] = Field(
|
|
46
|
+
default="xml",
|
|
47
|
+
description="Output format: 'concise' for brief results, 'detailed' for full context, 'xml' for structured"
|
|
48
|
+
)
|
|
49
|
+
) -> str:
|
|
50
|
+
"""Search past Claude conversations semantically to find relevant context.
|
|
51
|
+
|
|
52
|
+
WHEN TO USE THIS TOOL:
|
|
53
|
+
- User asks "what did we discuss about X?" or "find conversations about Y"
|
|
54
|
+
- You need context from previous work on similar problems
|
|
55
|
+
- User mentions "remember when" or "last time we"
|
|
56
|
+
- Debugging issues that may have been solved before
|
|
57
|
+
- Finding implementation patterns used in the project
|
|
58
|
+
|
|
59
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
60
|
+
- "What did we work on with Docker last week?"
|
|
61
|
+
- "Find all conversations about authentication"
|
|
62
|
+
- "How did we solve the memory leak issue?"
|
|
63
|
+
- "Search for discussions about database optimization"
|
|
64
|
+
|
|
65
|
+
This is the PRIMARY tool for conversation memory - use it liberally!
|
|
66
|
+
"""
|
|
67
|
+
# Map response_format to existing parameters
|
|
68
|
+
brief = response_format == "concise"
|
|
69
|
+
include_raw = response_format == "detailed"
|
|
70
|
+
|
|
71
|
+
return await tools.reflect_on_past(
|
|
72
|
+
ctx, query, limit, min_score, use_decay,
|
|
73
|
+
project, mode, brief, include_raw, response_format="xml"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Quick existence check - for fast validation
|
|
77
|
+
@mcp.tool(name="csr_quick_check")
|
|
78
|
+
async def csr_quick_check(
|
|
79
|
+
ctx: Context,
|
|
80
|
+
query: str = Field(
|
|
81
|
+
description="Topic or concept to check for existence"
|
|
82
|
+
),
|
|
83
|
+
min_score: float = Field(
|
|
84
|
+
default=0.3,
|
|
85
|
+
description="Minimum similarity score (0-1)"
|
|
86
|
+
),
|
|
87
|
+
project: Optional[str] = Field(
|
|
88
|
+
default=None,
|
|
89
|
+
description="Search specific project only"
|
|
90
|
+
)
|
|
91
|
+
) -> str:
|
|
92
|
+
"""Quick check if a topic was discussed before (returns count + top match only).
|
|
93
|
+
|
|
94
|
+
WHEN TO USE THIS TOOL:
|
|
95
|
+
- User asks "have we discussed X?" or "is there anything about Y?"
|
|
96
|
+
- You need a yes/no answer about topic existence
|
|
97
|
+
- Checking if a problem was encountered before
|
|
98
|
+
- Validating if a concept is familiar to the project
|
|
99
|
+
|
|
100
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
101
|
+
- "Have we talked about WebSockets?"
|
|
102
|
+
- "Is there any discussion about React hooks?"
|
|
103
|
+
- "Did we ever implement caching?"
|
|
104
|
+
|
|
105
|
+
Much faster than full search - use for existence checks!
|
|
106
|
+
"""
|
|
107
|
+
return await tools.quick_search(ctx, query, min_score, project)
|
|
108
|
+
|
|
109
|
+
# Time-based search - for recent work
|
|
110
|
+
@mcp.tool(name="csr_recent_work")
|
|
111
|
+
async def csr_recent_work(
|
|
112
|
+
ctx: Context,
|
|
113
|
+
limit: int = Field(
|
|
114
|
+
default=10,
|
|
115
|
+
description="Number of recent conversations to return"
|
|
116
|
+
),
|
|
117
|
+
group_by: str = Field(
|
|
118
|
+
default="conversation",
|
|
119
|
+
description="Group by 'conversation', 'day', or 'session'"
|
|
120
|
+
),
|
|
121
|
+
include_reflections: bool = Field(
|
|
122
|
+
default=True,
|
|
123
|
+
description="Include stored reflections"
|
|
124
|
+
),
|
|
125
|
+
project: Optional[str] = Field(
|
|
126
|
+
default=None,
|
|
127
|
+
description="Specific project or 'all' for cross-project"
|
|
128
|
+
),
|
|
129
|
+
response_format: Literal["concise", "detailed"] = Field(
|
|
130
|
+
default="concise",
|
|
131
|
+
description="Output verbosity level"
|
|
132
|
+
)
|
|
133
|
+
) -> str:
|
|
134
|
+
"""Get recent work conversations to understand current context.
|
|
135
|
+
|
|
136
|
+
WHEN TO USE THIS TOOL:
|
|
137
|
+
- User asks "what did we work on recently?" or "what were we doing?"
|
|
138
|
+
- Starting a new session and need context
|
|
139
|
+
- User says "continue from where we left off"
|
|
140
|
+
- Reviewing progress over time periods
|
|
141
|
+
|
|
142
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
143
|
+
- "What did we work on yesterday?"
|
|
144
|
+
- "Show me the last 5 things we discussed"
|
|
145
|
+
- "What have I been working on this week?"
|
|
146
|
+
- "Let's continue from last time"
|
|
147
|
+
|
|
148
|
+
Essential for session continuity and context awareness!
|
|
149
|
+
"""
|
|
150
|
+
return await tools.get_recent_work(ctx, group_by, limit, include_reflections, project)
|
|
151
|
+
|
|
152
|
+
# Time-constrained semantic search
|
|
153
|
+
@mcp.tool(name="csr_search_by_time")
|
|
154
|
+
async def csr_search_by_time(
|
|
155
|
+
ctx: Context,
|
|
156
|
+
query: str = Field(
|
|
157
|
+
description="Semantic search query"
|
|
158
|
+
),
|
|
159
|
+
time_range: Optional[str] = Field(
|
|
160
|
+
default=None,
|
|
161
|
+
description="Natural language time like 'last week', 'yesterday'"
|
|
162
|
+
),
|
|
163
|
+
since: Optional[str] = Field(
|
|
164
|
+
default=None,
|
|
165
|
+
description="ISO timestamp or relative time"
|
|
166
|
+
),
|
|
167
|
+
until: Optional[str] = Field(
|
|
168
|
+
default=None,
|
|
169
|
+
description="ISO timestamp or relative time"
|
|
170
|
+
),
|
|
171
|
+
limit: int = Field(
|
|
172
|
+
default=10,
|
|
173
|
+
description="Maximum number of results"
|
|
174
|
+
),
|
|
175
|
+
min_score: float = Field(
|
|
176
|
+
default=0.3,
|
|
177
|
+
description="Minimum similarity score"
|
|
178
|
+
),
|
|
179
|
+
project: Optional[str] = Field(
|
|
180
|
+
default=None,
|
|
181
|
+
description="Specific project or 'all'"
|
|
182
|
+
)
|
|
183
|
+
) -> str:
|
|
184
|
+
"""Search with time constraints for time-specific queries.
|
|
185
|
+
|
|
186
|
+
WHEN TO USE THIS TOOL:
|
|
187
|
+
- Query includes time references like "last week", "yesterday", "this month"
|
|
188
|
+
- User wants recent occurrences of a topic
|
|
189
|
+
- Debugging issues that started at a specific time
|
|
190
|
+
- Finding when something was first discussed
|
|
191
|
+
|
|
192
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
193
|
+
- "Docker errors from last week"
|
|
194
|
+
- "What did we discuss about testing yesterday?"
|
|
195
|
+
- "Authentication problems in the past 3 days"
|
|
196
|
+
- "Recent conversations about performance"
|
|
197
|
+
|
|
198
|
+
Combines semantic search with temporal filtering!
|
|
199
|
+
"""
|
|
200
|
+
return await tools.search_by_recency(
|
|
201
|
+
ctx, query, limit, min_score, project,
|
|
202
|
+
since, until, time_range
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# File-based search - for code archaeology
|
|
206
|
+
@mcp.tool(name="csr_search_by_file")
|
|
207
|
+
async def csr_search_by_file(
|
|
208
|
+
ctx: Context,
|
|
209
|
+
file_path: str = Field(
|
|
210
|
+
description="File path to search for (absolute or relative)"
|
|
211
|
+
),
|
|
212
|
+
limit: int = Field(
|
|
213
|
+
default=10,
|
|
214
|
+
description="Maximum number of results"
|
|
215
|
+
),
|
|
216
|
+
project: Optional[str] = Field(
|
|
217
|
+
default=None,
|
|
218
|
+
description="Search specific project only"
|
|
219
|
+
)
|
|
220
|
+
) -> str:
|
|
221
|
+
"""Find all conversations that analyzed or modified a specific file.
|
|
222
|
+
|
|
223
|
+
WHEN TO USE THIS TOOL:
|
|
224
|
+
- User asks "when did we modify X file?" or "who worked on Y?"
|
|
225
|
+
- Investigating file history beyond git
|
|
226
|
+
- Understanding why changes were made to a file
|
|
227
|
+
- Finding discussions about specific code files
|
|
228
|
+
|
|
229
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
230
|
+
- "When did we last modify server.py?"
|
|
231
|
+
- "Find all discussions about package.json"
|
|
232
|
+
- "What changes were made to the auth module?"
|
|
233
|
+
- "Who worked on the database schema?"
|
|
234
|
+
|
|
235
|
+
Perfect for code archaeology and understanding file evolution!
|
|
236
|
+
"""
|
|
237
|
+
return await tools.search_by_file(ctx, file_path, limit, project)
|
|
238
|
+
|
|
239
|
+
# Concept-based search - for thematic queries
|
|
240
|
+
@mcp.tool(name="csr_search_by_concept")
|
|
241
|
+
async def csr_search_by_concept(
|
|
242
|
+
ctx: Context,
|
|
243
|
+
concept: str = Field(
|
|
244
|
+
description="Development concept (e.g., 'security', 'testing', 'performance')"
|
|
245
|
+
),
|
|
246
|
+
limit: int = Field(
|
|
247
|
+
default=10,
|
|
248
|
+
description="Maximum number of results"
|
|
249
|
+
),
|
|
250
|
+
include_files: bool = Field(
|
|
251
|
+
default=True,
|
|
252
|
+
description="Include file information"
|
|
253
|
+
),
|
|
254
|
+
project: Optional[str] = Field(
|
|
255
|
+
default=None,
|
|
256
|
+
description="Search specific project only"
|
|
257
|
+
)
|
|
258
|
+
) -> str:
|
|
259
|
+
"""Search for conversations about specific development concepts or themes.
|
|
260
|
+
|
|
261
|
+
WHEN TO USE THIS TOOL:
|
|
262
|
+
- User asks about broad topics like "security", "testing", "performance"
|
|
263
|
+
- Looking for all discussions on a technical theme
|
|
264
|
+
- Gathering knowledge about how a concept is handled
|
|
265
|
+
- Finding patterns across multiple conversations
|
|
266
|
+
|
|
267
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
268
|
+
- "Show me all security-related discussions"
|
|
269
|
+
- "Find conversations about testing strategies"
|
|
270
|
+
- "What have we discussed about performance?"
|
|
271
|
+
- "Look for Docker-related conversations"
|
|
272
|
+
|
|
273
|
+
Ideal for thematic analysis and knowledge gathering!
|
|
274
|
+
"""
|
|
275
|
+
return await tools.search_by_concept(ctx, concept, limit, project, include_files)
|
|
276
|
+
|
|
277
|
+
# Insight storage - for knowledge persistence
|
|
278
|
+
@mcp.tool(name="csr_store_insight")
|
|
279
|
+
async def csr_store_insight(
|
|
280
|
+
ctx: Context,
|
|
281
|
+
content: str = Field(
|
|
282
|
+
description="The insight, solution, or learning to store"
|
|
283
|
+
),
|
|
284
|
+
tags: List[str] = Field(
|
|
285
|
+
default=[],
|
|
286
|
+
description="Tags for categorization (e.g., ['docker', 'debugging'])"
|
|
287
|
+
)
|
|
288
|
+
) -> str:
|
|
289
|
+
"""Store important insights, solutions, or learnings for future reference.
|
|
290
|
+
|
|
291
|
+
WHEN TO USE THIS TOOL:
|
|
292
|
+
- User says "remember this" or "store this solution"
|
|
293
|
+
- After solving a complex problem
|
|
294
|
+
- When discovering important patterns or gotchas
|
|
295
|
+
- User provides valuable configuration or setup info
|
|
296
|
+
- After successful debugging sessions
|
|
297
|
+
|
|
298
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
299
|
+
- "Remember this Docker configuration for next time"
|
|
300
|
+
- "Store this solution for the auth problem"
|
|
301
|
+
- "Save this debugging technique"
|
|
302
|
+
- "This is important - the API key goes in .env"
|
|
303
|
+
|
|
304
|
+
Critical for building institutional memory!
|
|
305
|
+
"""
|
|
306
|
+
return await tools.store_reflection(ctx, content, tags)
|
|
307
|
+
|
|
308
|
+
# Aggregated insights - for analysis
|
|
309
|
+
@mcp.tool(name="csr_search_insights")
|
|
310
|
+
async def csr_search_insights(
|
|
311
|
+
ctx: Context,
|
|
312
|
+
query: str = Field(
|
|
313
|
+
description="Topic to analyze across conversations"
|
|
314
|
+
),
|
|
315
|
+
project: Optional[str] = Field(
|
|
316
|
+
default=None,
|
|
317
|
+
description="Search specific project only"
|
|
318
|
+
)
|
|
319
|
+
) -> str:
|
|
320
|
+
"""Get aggregated insights and patterns from search results.
|
|
321
|
+
|
|
322
|
+
WHEN TO USE THIS TOOL:
|
|
323
|
+
- User wants patterns or trends, not individual results
|
|
324
|
+
- Analyzing how a topic evolved over time
|
|
325
|
+
- Understanding common themes across conversations
|
|
326
|
+
- Getting a high-level view without details
|
|
327
|
+
|
|
328
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
329
|
+
- "What patterns do we see in error handling?"
|
|
330
|
+
- "Summarize our authentication discussions"
|
|
331
|
+
- "What are the common Docker issues we face?"
|
|
332
|
+
- "Give me insights about our testing approach"
|
|
333
|
+
|
|
334
|
+
Provides analysis, not just search results!
|
|
335
|
+
"""
|
|
336
|
+
return await tools.search_summary(ctx, query, project)
|
|
337
|
+
|
|
338
|
+
# Pagination support - for deep dives
|
|
339
|
+
@mcp.tool(name="csr_get_more")
|
|
340
|
+
async def csr_get_more(
|
|
341
|
+
ctx: Context,
|
|
342
|
+
query: str = Field(
|
|
343
|
+
description="The original search query"
|
|
344
|
+
),
|
|
345
|
+
offset: int = Field(
|
|
346
|
+
default=3,
|
|
347
|
+
description="Number of results to skip"
|
|
348
|
+
),
|
|
349
|
+
limit: int = Field(
|
|
350
|
+
default=3,
|
|
351
|
+
description="Number of additional results"
|
|
352
|
+
),
|
|
353
|
+
min_score: float = Field(
|
|
354
|
+
default=0.3,
|
|
355
|
+
description="Minimum similarity score"
|
|
356
|
+
),
|
|
357
|
+
project: Optional[str] = Field(
|
|
358
|
+
default=None,
|
|
359
|
+
description="Search specific project only"
|
|
360
|
+
)
|
|
361
|
+
) -> str:
|
|
362
|
+
"""Get additional search results for paginated exploration.
|
|
363
|
+
|
|
364
|
+
WHEN TO USE THIS TOOL:
|
|
365
|
+
- User says "show me more" after a search
|
|
366
|
+
- Initial results weren't sufficient
|
|
367
|
+
- Deep diving into a topic
|
|
368
|
+
- User wants comprehensive coverage
|
|
369
|
+
|
|
370
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
371
|
+
- "Show me more results"
|
|
372
|
+
- "What else is there?"
|
|
373
|
+
- "Keep searching"
|
|
374
|
+
- "I need more examples"
|
|
375
|
+
|
|
376
|
+
Use after initial search when more context is needed!
|
|
377
|
+
"""
|
|
378
|
+
return await tools.get_more_results(ctx, query, offset, limit, min_score, project)
|
|
379
|
+
|
|
380
|
+
# Full conversation retrieval
|
|
381
|
+
@mcp.tool(name="csr_get_full_conversation")
|
|
382
|
+
async def csr_get_full_conversation(
|
|
383
|
+
ctx: Context,
|
|
384
|
+
conversation_id: str = Field(
|
|
385
|
+
description="Conversation ID from search results (cid field)"
|
|
386
|
+
),
|
|
387
|
+
project: Optional[str] = Field(
|
|
388
|
+
default=None,
|
|
389
|
+
description="Optional project name to help locate the file"
|
|
390
|
+
)
|
|
391
|
+
) -> str:
|
|
392
|
+
"""Get the full conversation file path to read complete context.
|
|
393
|
+
|
|
394
|
+
WHEN TO USE THIS TOOL:
|
|
395
|
+
- Search result was truncated but needs full context
|
|
396
|
+
- User wants to see the entire conversation
|
|
397
|
+
- Debugging requires complete conversation history
|
|
398
|
+
- Following up on a specific conversation ID
|
|
399
|
+
|
|
400
|
+
EXAMPLES THAT TRIGGER THIS TOOL:
|
|
401
|
+
- "Show me the full conversation for cid_12345"
|
|
402
|
+
- "I need to see everything from that discussion"
|
|
403
|
+
- "Get the complete context for that result"
|
|
404
|
+
|
|
405
|
+
Returns file path for agents to read complete conversations!
|
|
406
|
+
"""
|
|
407
|
+
return await tools.get_full_conversation(ctx, conversation_id, project)
|