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.
- package/mcp-server/run-mcp-clean.sh +29 -0
- package/mcp-server/src/utils.py +17 -55
- package/package.json +2 -1
|
@@ -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
|
package/mcp-server/src/utils.py
CHANGED
|
@@ -3,31 +3,7 @@
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def
|
|
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
|
-
#
|
|
51
|
-
|
|
52
|
-
|
|
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 =
|
|
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
|
-
#
|
|
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": "
|
|
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",
|