refactor: consolidate hook scripts and fixed issue from review

This commit is contained in:
Tal Muskal
2026-04-08 20:17:23 +03:00
parent 4f1434720c
commit e47fa1b5bf
7 changed files with 32 additions and 75 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ Give your AI a persistent memory -- mine projects and conversations into a searc
## Prerequisites ## Prerequisites
- Python 3.10+ - Python 3.9+
- Codex CLI installed and configured - Codex CLI installed and configured
- `pip install mempalace` - `pip install mempalace`
+3 -3
View File
@@ -6,7 +6,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "./hooks/mempal-session-start-hook.sh" "command": "${CODEX_PLUGIN_ROOT}/hooks/mempal-hook.sh session-start"
} }
] ]
} }
@@ -17,7 +17,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "./hooks/mempal-stop-hook.sh" "command": "${CODEX_PLUGIN_ROOT}/hooks/mempal-hook.sh stop"
} }
] ]
} }
@@ -28,7 +28,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "./hooks/mempal-precompact-hook.sh" "command": "${CODEX_PLUGIN_ROOT}/hooks/mempal-hook.sh precompact"
} }
] ]
} }
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
HOOK_NAME="${1:?Usage: mempal-hook.sh <hook-name>}"
INPUT_FILE=$(mktemp) || { echo "Failed to create temp file" >&2; exit 1; }
cat > "$INPUT_FILE"
cat "$INPUT_FILE" | python3 -m mempalace hook run --hook "$HOOK_NAME" --harness codex
EXIT_CODE=$?
rm -f "$INPUT_FILE" 2>/dev/null
exit $EXIT_CODE
@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
# Capture stdin (hook input from Codex)
INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/mempal-precompact-hook-$$.json")
cat > "$INPUT_FILE"
# Pipe to Python CLI with codex harness
cat "$INPUT_FILE" | python3 -m mempalace hook run --hook precompact --harness codex
EXIT_CODE=$?
# Cleanup
rm -f "$INPUT_FILE" 2>/dev/null
exit $EXIT_CODE
@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
# Capture stdin (hook input from Codex)
INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/mempal-session-start-hook-$$.json")
cat > "$INPUT_FILE"
# Pipe to Python CLI with codex harness
cat "$INPUT_FILE" | python3 -m mempalace hook run --hook session-start --harness codex
EXIT_CODE=$?
# Cleanup
rm -f "$INPUT_FILE" 2>/dev/null
exit $EXIT_CODE
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
# Capture stdin (hook input from Codex)
INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/mempal-stop-hook-$$.json")
cat > "$INPUT_FILE"
# Pipe to Python CLI with codex harness
cat "$INPUT_FILE" | python3 -m mempalace hook run --hook stop --harness codex
EXIT_CODE=$?
# Cleanup
rm -f "$INPUT_FILE" 2>/dev/null
exit $EXIT_CODE
+19 -26
View File
@@ -53,8 +53,15 @@ def _count_human_messages(transcript_path: str) -> int:
msg = entry.get("message", {}) msg = entry.get("message", {})
if isinstance(msg, dict) and msg.get("role") == "user": if isinstance(msg, dict) and msg.get("role") == "user":
content = msg.get("content", "") content = msg.get("content", "")
if isinstance(content, str) and "<command-message>" in content: if isinstance(content, str):
continue if "<command-message>" in content:
continue
elif isinstance(content, list):
text = " ".join(
b.get("text", "") for b in content if isinstance(b, dict)
)
if "<command-message>" in text:
continue
count += 1 count += 1
except (json.JSONDecodeError, AttributeError): except (json.JSONDecodeError, AttributeError):
pass pass
@@ -96,35 +103,19 @@ def _maybe_auto_ingest():
pass pass
def _parse_claude_code_input(data: dict) -> dict: SUPPORTED_HARNESSES = {"claude-code", "codex"}
"""Parse stdin JSON for the claude-code harness."""
return {
"session_id": _sanitize_session_id(str(data.get("session_id", "unknown"))),
"stop_hook_active": data.get("stop_hook_active", False),
"transcript_path": str(data.get("transcript_path", "")),
}
def _parse_codex_input(data: dict) -> dict:
"""Parse stdin JSON for the codex harness."""
return {
"session_id": _sanitize_session_id(str(data.get("session_id", "unknown"))),
"stop_hook_active": data.get("stop_hook_active", False),
"transcript_path": str(data.get("transcript_path", "")),
}
def _parse_harness_input(data: dict, harness: str) -> dict: def _parse_harness_input(data: dict, harness: str) -> dict:
"""Parse stdin JSON according to the harness type.""" """Parse stdin JSON according to the harness type."""
parsers = { if harness not in SUPPORTED_HARNESSES:
"claude-code": _parse_claude_code_input,
"codex": _parse_codex_input,
}
parser = parsers.get(harness)
if parser is None:
print(f"Unknown harness: {harness}", file=sys.stderr) print(f"Unknown harness: {harness}", file=sys.stderr)
sys.exit(1) sys.exit(1)
return parser(data) return {
"session_id": _sanitize_session_id(str(data.get("session_id", "unknown"))),
"stop_hook_active": data.get("stop_hook_active", False),
"transcript_path": str(data.get("transcript_path", "")),
}
def hook_stop(data: dict, harness: str): def hook_stop(data: dict, harness: str):
@@ -135,7 +126,7 @@ def hook_stop(data: dict, harness: str):
transcript_path = parsed["transcript_path"] transcript_path = parsed["transcript_path"]
# If already in a save cycle, let through (infinite-loop prevention) # If already in a save cycle, let through (infinite-loop prevention)
if stop_hook_active in (True, "True", "true"): if str(stop_hook_active).lower() in ("true", "1", "yes"):
_output({}) _output({})
return return
@@ -204,6 +195,7 @@ def hook_precompact(data: dict, harness: str):
[sys.executable, "-m", "mempalace", "mine", mempal_dir], [sys.executable, "-m", "mempalace", "mine", mempal_dir],
stdout=log_f, stdout=log_f,
stderr=log_f, stderr=log_f,
timeout=60,
) )
except OSError: except OSError:
pass pass
@@ -217,6 +209,7 @@ def run_hook(hook_name: str, harness: str):
try: try:
data = json.load(sys.stdin) data = json.load(sys.stdin)
except (json.JSONDecodeError, EOFError): except (json.JSONDecodeError, EOFError):
_log("WARNING: Failed to parse stdin JSON, proceeding with empty data")
data = {} data = {}
hooks = { hooks = {