Files
wehub-resource-sync c3749daf48
Tests / test-linux (3.13) (push) Failing after 0s
Tests / test-linux (3.11) (push) Failing after 1s
Tests / lint (push) Failing after 0s
Tests / test-linux (3.9) (push) Failing after 1s
Docker / build (push) Failing after 1s
Docker / build-gpu (push) Failing after 2s
Tests / test-windows (push) Has been cancelled
Tests / test-macos (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:03:03 +08:00

83 lines
2.8 KiB
Bash
Executable File

#!/bin/bash
# MEMPALACE CURSOR WAKE HOOK — Session-start memory recall
#
# Cursor "sessionStart" hook. This is a Cursor-only capability —
# Claude Code's third-party-hooks compatibility layer does not have
# an equivalent event with the same "inject context into the agent's
# initial system message" semantics.
#
# Behaviour:
# 1. Parse Cursor's sessionStart payload (conversation_id /
# session_id, is_background_agent, composer_mode, plus the
# common workspace_roots field).
# 2. Infer the wing from basename(workspace_roots[0]).
# 3. Return {"additional_context": "..."} instructing the agent to
# scope its memory recall by calling mempalace_search +
# mempalace_diary_read with wing=<inferred>.
#
# sessionStart is documented as fire-and-forget — Cursor does not
# enforce a blocking response and does not consume "continue" /
# "user_message" — but "additional_context" is honoured and added to
# the conversation's initial system context. Verified in
# cursor.com/docs/hooks.md (fetched 2026-05-27).
#
# === INSTALL ===
#
# Add to ~/.cursor/hooks.json (or .cursor/hooks.json for project
# scope) under "sessionStart":
#
# {
# "version": 1,
# "hooks": {
# "sessionStart": [
# { "command": "/absolute/path/to/mempal_wake_hook_cursor.sh" }
# ]
# }
# }
_mempal_self="${BASH_SOURCE[0]:-$0}"
_mempal_dir="$(cd "$(dirname "$_mempal_self")" 2>/dev/null && pwd)"
# shellcheck source=lib/common.sh
. "$_mempal_dir/lib/common.sh"
if mempal_is_disabled; then
mempal_emit '{}'
exit 0
fi
INPUT="$(cat)"
mempal_parse_stdin "$INPUT"
if [ "$MEMPAL_PARSE_OK" != "1" ]; then
mempal_dump_bad_input "$INPUT" "sessionStart"
mempal_emit '{}'
exit 0
fi
WING="$(mempal_infer_wing "$MEMPAL_WORKSPACE")"
mempal_log "sessionStart" "$MEMPAL_CONV_ID" \
"workspace=$MEMPAL_WORKSPACE wing=$WING"
# Emit the additional_context payload via Python -c (rather than a
# heredoc) so the JSON encoding survives wings whose name contains
# characters that would otherwise need shell escaping, and so the
# inferred wing arrives as an argv positional. The MCP tool names
# referenced here are verified against mempalace/mcp_server.py:
# mempalace_search and mempalace_diary_read both exist and accept
# the wing parameter.
"$MEMPAL_PYTHON_BIN" -c '
import json, sys
wing = sys.argv[1] if len(sys.argv) > 1 else "cursor_session"
ctx = (
"MemPalace wake-up. The Cursor workspace maps to wing=" + wing + ". "
"Before answering anything that touches past work in this "
"project, call mempalace_search (wing=" + wing + ", "
"query=<relevant keywords>) and mempalace_diary_read "
"(agent_name=cursor-ide, wing=" + wing + ", last_n=10). "
"Use what you find verbatim where it answers the question; "
"never summarise the user'"'"'s own words."
)
print(json.dumps({"additional_context": ctx}))
' "$WING"