claude-self-reflect 2.8.9 → 3.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.
@@ -0,0 +1,29 @@
1
+ #!/bin/bash
2
+ # MCP Server Runner with Clean Output
3
+ # This wrapper filters INFO messages from stderr to prevent Claude Desktop from showing them as errors
4
+
5
+ # Get the directory of this script
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+
8
+ # Activate virtual environment if it exists
9
+ if [ -d "$SCRIPT_DIR/venv" ]; then
10
+ source "$SCRIPT_DIR/venv/bin/activate"
11
+ elif [ -d "$SCRIPT_DIR/../venv" ]; then
12
+ source "$SCRIPT_DIR/../venv/bin/activate"
13
+ fi
14
+
15
+ # Run the MCP server and filter stderr
16
+ # INFO messages go to /dev/null, actual errors go to stderr
17
+ python -u -m src 2>&1 | while IFS= read -r line; do
18
+ # Check if the line contains INFO level logging
19
+ if [[ "$line" == *"INFO"* ]] && [[ "$line" == *"Starting MCP server"* ]]; then
20
+ # Silently ignore the startup message
21
+ continue
22
+ elif [[ "$line" == *"INFO"* ]]; then
23
+ # Send other INFO messages to stdout (they won't show as errors)
24
+ echo "$line"
25
+ else
26
+ # Send actual errors/warnings to stderr
27
+ echo "$line" >&2
28
+ fi
29
+ done
@@ -3,31 +3,7 @@
3
3
  from pathlib import Path
4
4
 
5
5
 
6
- def path_to_dash_encoded(path: str) -> str:
7
- """
8
- Convert a file path to dash-encoded format used in Claude logs.
9
-
10
- Examples:
11
- - /Users/kyle/projects/my-app -> -Users-kyle-projects-my-app
12
- - /home/user/Code/project -> -home-user-Code-project
13
-
14
- Args:
15
- path: File system path
16
-
17
- Returns:
18
- Dash-encoded path string
19
- """
20
- # Convert to Path object and get parts
21
- path_obj = Path(path)
22
-
23
- # Remove empty parts and join with dashes
24
- parts = [p for p in path_obj.parts if p and p != '/']
25
-
26
- # Join with dashes and add leading dash
27
- return '-' + '-'.join(parts)
28
-
29
-
30
- def normalize_project_name(project_path: str) -> str:
6
+ def normalize_project_name(project_path: str, _depth: int = 0) -> str:
31
7
  """
32
8
  Normalize project name for consistent hashing across import/search.
33
9
 
@@ -37,9 +13,11 @@ def normalize_project_name(project_path: str) -> str:
37
13
  - Regular file paths: /path/to/project/file.txt -> project
38
14
  - Regular paths: /path/to/project -> project
39
15
  - Already normalized: project -> project
16
+ - Docker mount paths: /logs/-Users-name-projects-project -> project
40
17
 
41
18
  Args:
42
19
  project_path: Project path or name in any format
20
+ _depth: Internal recursion depth counter (do not use)
43
21
 
44
22
  Returns:
45
23
  Normalized project name suitable for consistent hashing
@@ -47,9 +25,9 @@ def normalize_project_name(project_path: str) -> str:
47
25
  if not project_path:
48
26
  return ""
49
27
 
50
- # Project discovery markers - common parent directories that indicate project roots
51
- PROJECT_MARKERS = {'projects', 'code', 'Code', 'repos', 'repositories',
52
- 'dev', 'Development', 'work', 'src', 'github'}
28
+ # Prevent infinite recursion on malformed inputs
29
+ if _depth > 10:
30
+ return Path(project_path).name
53
31
 
54
32
  # Remove trailing slashes
55
33
  project_path = project_path.rstrip('/')
@@ -65,28 +43,15 @@ def normalize_project_name(project_path: str) -> str:
65
43
  path_parts = Path(path_str).parts
66
44
 
67
45
  # Look for common project parent directories
68
- project_parents = PROJECT_MARKERS
46
+ project_parents = {'projects', 'code', 'Code', 'repos', 'repositories',
47
+ 'dev', 'Development', 'work', 'src', 'github'}
69
48
 
70
49
  # Find the project name after a known parent directory
71
50
  for i, part in enumerate(path_parts):
72
51
  if part.lower() in project_parents and i + 1 < len(path_parts):
73
52
  # Everything after the parent directory is the project name
74
- remaining = path_parts[i + 1:]
75
-
76
- # Use segment-based approach for complex paths
77
- # Return the most likely project name from remaining segments
78
- if remaining:
79
- # If it's a single segment, return it
80
- if len(remaining) == 1:
81
- return remaining[0]
82
- # For multiple segments, look for project-like patterns
83
- for r in remaining:
84
- r_lower = r.lower()
85
- # Prioritize segments with project indicators
86
- if any(ind in r_lower for ind in ['app', 'service', 'project', 'api', 'client']):
87
- return r
88
-
89
53
  # Join remaining parts with dash if project name has multiple components
54
+ remaining = path_parts[i + 1:]
90
55
  return '-'.join(remaining)
91
56
 
92
57
  # Fallback: just use the last component
@@ -96,27 +61,24 @@ def normalize_project_name(project_path: str) -> str:
96
61
  # Pattern: /path/to/-Users-...-projects-..../filename
97
62
  path_obj = Path(project_path)
98
63
 
64
+ # Check if this is a Docker mount path specifically
65
+ # e.g., /logs/-Users-ramakrishnanannaswamy-projects-claude-self-reflect
66
+ if str(path_obj).startswith("/logs/") and path_obj.name.startswith("-"):
67
+ # Process this directory name recursively (Docker case only)
68
+ return normalize_project_name(path_obj.name, _depth + 1)
69
+
99
70
  # Look for a parent directory that starts with dash (Claude logs format)
100
71
  for parent in path_obj.parents:
101
72
  parent_name = parent.name
102
73
  if parent_name.startswith("-"):
103
74
  # Found a Claude logs directory, process it
104
- return normalize_project_name(parent_name)
75
+ return normalize_project_name(parent_name, _depth + 1)
105
76
 
106
77
  # Handle regular paths - if it's a file, get the parent directory
107
78
  # Otherwise use the directory/project name itself
108
79
  if path_obj.suffix: # It's a file (has an extension)
109
- # Check if .claude is anywhere in the parent path
110
- for parent in path_obj.parents:
111
- if parent.name == '.claude' and parent.parent:
112
- return parent.parent.name
113
- # No .claude found, use immediate parent
80
+ # Use the parent directory name
114
81
  return path_obj.parent.name
115
82
  else:
116
- # Check if any parent in the path is .claude
117
- for parent in [path_obj] + list(path_obj.parents):
118
- if parent.name == '.claude' and parent.parent:
119
- # Return the parent of .claude (the project directory)
120
- return parent.parent.name
121
83
  # Use the directory name itself
122
84
  return path_obj.name
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-self-reflect",
3
- "version": "2.8.9",
3
+ "version": "3.0.0",
4
4
  "description": "Give Claude perfect memory of all your conversations - Installation wizard for Python MCP server",
5
5
  "keywords": [
6
6
  "claude",
@@ -38,6 +38,7 @@
38
38
  "mcp-server/src/**/*.py",
39
39
  "mcp-server/pyproject.toml",
40
40
  "mcp-server/run-mcp.sh",
41
+ "mcp-server/run-mcp-clean.sh",
41
42
  "mcp-server/run-mcp-docker.sh",
42
43
  "scripts/import-*.py",
43
44
  "scripts/delta-metadata-update-safe.py",