claude-self-reflect 2.4.0 → 2.4.2

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.
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ # Run the MCP server in the Docker container with stdin attached
3
+ # Using python -u for unbuffered output
4
+ # Using server.py which supports local embeddings (not server_v2.py)
5
+ docker exec -i claude-reflection-mcp python -u -m src
@@ -17,7 +17,8 @@ def main():
17
17
  from .server import mcp
18
18
 
19
19
  # Run the server with the specified transport
20
- mcp.run(transport=args.transport)
20
+ # Disable FastMCP banner to prevent JSON output interference
21
+ mcp.run(transport=args.transport, show_banner=False)
21
22
 
22
23
  if __name__ == "__main__":
23
24
  main()
@@ -12,10 +12,24 @@ from fastmcp import FastMCP, Context
12
12
  from pydantic import BaseModel, Field
13
13
  from qdrant_client import AsyncQdrantClient, models
14
14
  from qdrant_client.models import (
15
- PointStruct, VectorParams, Distance,
16
- FormulaQuery, DecayParamsExpression, SumExpression,
17
- DatetimeExpression, DatetimeKeyExpression
15
+ PointStruct, VectorParams, Distance
18
16
  )
17
+
18
+ # Try to import newer Qdrant API for native decay
19
+ try:
20
+ from qdrant_client.models import (
21
+ Query, Formula, Expression, MultExpression,
22
+ ExpDecayExpression, DecayParamsExpression,
23
+ SearchRequest, NamedQuery
24
+ )
25
+ NATIVE_DECAY_AVAILABLE = True
26
+ except ImportError:
27
+ # Fall back to older API
28
+ from qdrant_client.models import (
29
+ FormulaQuery, DecayParamsExpression, SumExpression,
30
+ DatetimeExpression, DatetimeKeyExpression
31
+ )
32
+ NATIVE_DECAY_AVAILABLE = False
19
33
  import voyageai
20
34
  from dotenv import load_dotenv
21
35
 
@@ -176,11 +190,56 @@ async def reflect_on_past(
176
190
  # Search each collection
177
191
  for collection_name in all_collections:
178
192
  try:
179
- if should_use_decay and USE_NATIVE_DECAY:
180
- # Use native Qdrant decay
181
- await ctx.debug(f"Using NATIVE Qdrant decay for {collection_name}")
193
+ if should_use_decay and USE_NATIVE_DECAY and NATIVE_DECAY_AVAILABLE:
194
+ # Use native Qdrant decay with newer API
195
+ await ctx.debug(f"Using NATIVE Qdrant decay (new API) for {collection_name}")
196
+
197
+ # Build the query with native Qdrant decay formula using newer API
198
+ query_obj = Query(
199
+ nearest=query_embedding,
200
+ formula=Formula(
201
+ sum=[
202
+ # Original similarity score
203
+ Expression(variable="score"),
204
+ # Decay boost term
205
+ Expression(
206
+ mult=MultExpression(
207
+ mult=[
208
+ # Decay weight
209
+ Expression(constant=DECAY_WEIGHT),
210
+ # Exponential decay function
211
+ Expression(
212
+ exp_decay=DecayParamsExpression(
213
+ # Use timestamp field for decay
214
+ x=Expression(datetime_key="timestamp"),
215
+ # Decay from current time (server-side)
216
+ target=Expression(datetime="now"),
217
+ # Scale in milliseconds
218
+ scale=DECAY_SCALE_DAYS * 24 * 60 * 60 * 1000,
219
+ # Standard exponential decay midpoint
220
+ midpoint=0.5
221
+ )
222
+ )
223
+ ]
224
+ )
225
+ )
226
+ ]
227
+ )
228
+ )
229
+
230
+ # Execute query with native decay (new API)
231
+ results = await qdrant_client.query_points(
232
+ collection_name=collection_name,
233
+ query=query_obj,
234
+ limit=limit,
235
+ score_threshold=min_score,
236
+ with_payload=True
237
+ )
238
+ elif should_use_decay and USE_NATIVE_DECAY and not NATIVE_DECAY_AVAILABLE:
239
+ # Use native Qdrant decay with older API
240
+ await ctx.debug(f"Using NATIVE Qdrant decay (legacy API) for {collection_name}")
182
241
 
183
- # Build the query with native Qdrant decay formula
242
+ # Build the query with native Qdrant decay formula using older API
184
243
  query_obj = FormulaQuery(
185
244
  nearest=query_embedding,
186
245
  formula=SumExpression(
@@ -42,11 +42,11 @@ DECAY_SCALE_DAYS = float(os.getenv('DECAY_SCALE_DAYS', '90'))
42
42
  # Initialize Voyage AI client
43
43
  voyage_client = voyageai.Client(api_key=VOYAGE_API_KEY) if VOYAGE_API_KEY else None
44
44
 
45
- # Debug environment loading
46
- print(f"[DEBUG] Qdrant Native Decay Server v2.0.0")
47
- print(f"[DEBUG] ENABLE_MEMORY_DECAY: {ENABLE_MEMORY_DECAY}")
48
- print(f"[DEBUG] DECAY_WEIGHT: {DECAY_WEIGHT}")
49
- print(f"[DEBUG] DECAY_SCALE_DAYS: {DECAY_SCALE_DAYS}")
45
+ # Debug environment loading (disabled for production)
46
+ # print(f"[DEBUG] Qdrant Native Decay Server v2.0.0")
47
+ # print(f"[DEBUG] ENABLE_MEMORY_DECAY: {ENABLE_MEMORY_DECAY}")
48
+ # print(f"[DEBUG] DECAY_WEIGHT: {DECAY_WEIGHT}")
49
+ # print(f"[DEBUG] DECAY_SCALE_DAYS: {DECAY_SCALE_DAYS}")
50
50
 
51
51
 
52
52
  class SearchResult(BaseModel):
@@ -246,5 +246,9 @@ async def store_reflection(
246
246
  return f"Failed to store reflection: {str(e)}"
247
247
 
248
248
 
249
- # Debug output
250
- print(f"[DEBUG] FastMCP server v2.0.0 created with native Qdrant decay")
249
+ # Debug output (disabled for production)
250
+ # print(f"[DEBUG] FastMCP server v2.0.0 created with native Qdrant decay")
251
+
252
+ # Run the server when executed as main module
253
+ if __name__ == "__main__":
254
+ mcp.run(transport="stdio", show_banner=False)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-self-reflect",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "description": "Give Claude perfect memory of all your conversations - Installation wizard for Python MCP server",
5
5
  "keywords": [
6
6
  "claude",
@@ -32,8 +32,12 @@
32
32
  "mcp-server/src/**/*.py",
33
33
  "mcp-server/pyproject.toml",
34
34
  "mcp-server/run-mcp.sh",
35
+ "mcp-server/run-mcp-docker.sh",
35
36
  "scripts/import-*.py",
36
37
  ".claude/agents/*.md",
38
+ "docker-compose.yaml",
39
+ "Dockerfile.*",
40
+ ".env.example",
37
41
  "README.md",
38
42
  "LICENSE"
39
43
  ],
@@ -19,6 +19,12 @@ from qdrant_client.models import (
19
19
  Filter, FieldCondition, MatchValue
20
20
  )
21
21
 
22
+ from tenacity import (
23
+ retry,
24
+ stop_after_attempt,
25
+ wait_random_exponential,
26
+ )
27
+
22
28
  # Configuration
23
29
  QDRANT_URL = os.getenv("QDRANT_URL", "http://localhost:6333")
24
30
  LOGS_DIR = os.getenv("LOGS_DIR", "/logs")
@@ -54,6 +60,15 @@ else:
54
60
  # Initialize Qdrant client
55
61
  client = QdrantClient(url=QDRANT_URL)
56
62
 
63
+
64
+ def log_retry_state(retry_state):
65
+ print(f"Retrying function '{retry_state.fn.__name__}' for the {retry_state.attempt_number} time.")
66
+ print(f"----> Waiting for {retry_state.next_action.sleep} seconds before next attempt.")
67
+
68
+ @retry(wait=wait_random_exponential(multiplier=2, min=30, max=120), stop=stop_after_attempt(6), before_sleep=log_retry_state)
69
+ def embed_with_backoff(**kwargs):
70
+ return voyage_client.embed(**kwargs)
71
+
57
72
  def generate_embeddings(texts: List[str]) -> List[List[float]]:
58
73
  """Generate embeddings for a list of texts."""
59
74
  if PREFER_LOCAL_EMBEDDINGS or not VOYAGE_API_KEY:
@@ -62,7 +77,7 @@ def generate_embeddings(texts: List[str]) -> List[List[float]]:
62
77
  return [embedding.tolist() for embedding in embeddings]
63
78
  else:
64
79
  # Voyage AI embeddings
65
- result = voyage_client.embed(
80
+ result = embed_with_backoff(
66
81
  texts=texts,
67
82
  model="voyage-3-large",
68
83
  input_type="document"