160 lines
5.6 KiB
Python
160 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Prepare a MemPalace v3.0.0 integration packet for Ezra's Hermes home."""
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
PACKAGE_SPEC = "mempalace==3.0.0"
|
|
DEFAULT_HERMES_HOME = "~/.hermes/"
|
|
DEFAULT_SESSIONS_DIR = "~/.hermes/sessions/"
|
|
DEFAULT_PALACE_PATH = "~/.mempalace/palace"
|
|
DEFAULT_WING = "ezra_home"
|
|
|
|
|
|
def build_yaml_template(wing: str, palace_path: str) -> str:
|
|
return (
|
|
f"wing: {wing}\n"
|
|
f"palace: {palace_path}\n"
|
|
"rooms:\n"
|
|
" - name: sessions\n"
|
|
" description: Conversation history and durable agent transcripts\n"
|
|
" globs:\n"
|
|
" - \"*.json\"\n"
|
|
" - \"*.jsonl\"\n"
|
|
" - name: config\n"
|
|
" description: Hermes configuration and runtime settings\n"
|
|
" globs:\n"
|
|
" - \"*.yaml\"\n"
|
|
" - \"*.yml\"\n"
|
|
" - \"*.toml\"\n"
|
|
" - name: docs\n"
|
|
" description: Notes, markdown docs, and operating reports\n"
|
|
" globs:\n"
|
|
" - \"*.md\"\n"
|
|
" - \"*.txt\"\n"
|
|
"people: []\n"
|
|
"projects: []\n"
|
|
)
|
|
|
|
|
|
def build_plan(overrides: dict | None = None) -> dict:
|
|
overrides = overrides or {}
|
|
hermes_home = overrides.get("hermes_home", DEFAULT_HERMES_HOME)
|
|
sessions_dir = overrides.get("sessions_dir", DEFAULT_SESSIONS_DIR)
|
|
palace_path = overrides.get("palace_path", DEFAULT_PALACE_PATH)
|
|
wing = overrides.get("wing", DEFAULT_WING)
|
|
yaml_template = build_yaml_template(wing=wing, palace_path=palace_path)
|
|
|
|
config_home = hermes_home[:-1] if hermes_home.endswith("/") else hermes_home
|
|
plan = {
|
|
"package_spec": PACKAGE_SPEC,
|
|
"hermes_home": hermes_home,
|
|
"sessions_dir": sessions_dir,
|
|
"palace_path": palace_path,
|
|
"wing": wing,
|
|
"config_path": f"{config_home}/mempalace.yaml",
|
|
"install_command": f"pip install {PACKAGE_SPEC}",
|
|
"init_command": f"mempalace init {hermes_home} --yes",
|
|
"mine_home_command": f"echo \"\" | mempalace mine {hermes_home}",
|
|
"mine_sessions_command": f"echo \"\" | mempalace mine {sessions_dir} --mode convos",
|
|
"search_command": 'mempalace search "your common queries"',
|
|
"wake_up_command": "mempalace wake-up",
|
|
"mcp_command": "hermes mcp add mempalace -- python -m mempalace.mcp_server",
|
|
"yaml_template": yaml_template,
|
|
"gotchas": [
|
|
"`mempalace init` is still interactive in room approval flow; write mempalace.yaml manually if the init output stalls.",
|
|
"The yaml key is `wing:` not `wings:`. Using the wrong key causes mine/setup failures.",
|
|
"Pipe empty stdin into mining commands (`echo \"\" | ...`) to avoid the entity-detector stdin hang on larger directories.",
|
|
"First mine downloads the ChromaDB embedding model cache (~79MB).",
|
|
"Report Ezra's before/after metrics back to issue #568 after live installation and retrieval tests.",
|
|
],
|
|
}
|
|
return plan
|
|
|
|
|
|
def render_markdown(plan: dict) -> str:
|
|
gotchas = "\n".join(f"- {item}" for item in plan["gotchas"])
|
|
return f"""# MemPalace v3.0.0 — Ezra Integration Packet
|
|
|
|
This packet turns issue #570 into an executable, reviewable integration plan for Ezra's Hermes home.
|
|
It is a repo-side scaffold: no live Ezra host changes are claimed in this artifact.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
{plan['install_command']}
|
|
{plan['init_command']}
|
|
cat > {plan['config_path']} <<'YAML'
|
|
{plan['yaml_template'].rstrip()}
|
|
YAML
|
|
{plan['mine_home_command']}
|
|
{plan['mine_sessions_command']}
|
|
{plan['search_command']}
|
|
{plan['wake_up_command']}
|
|
{plan['mcp_command']}
|
|
```
|
|
|
|
## Manual config template
|
|
|
|
```yaml
|
|
{plan['yaml_template'].rstrip()}
|
|
```
|
|
|
|
## Why this shape
|
|
|
|
- `wing: {plan['wing']}` matches the issue's Ezra-specific integration target.
|
|
- `rooms` split the mined material into sessions, config, and docs to keep retrieval interpretable.
|
|
- Mining commands pipe empty stdin to avoid the interactive entity-detector hang noted in the evaluation.
|
|
|
|
## Gotchas
|
|
|
|
{gotchas}
|
|
|
|
## Report back to #568
|
|
|
|
After live execution on Ezra's actual environment, post back to #568 with:
|
|
- install result
|
|
- mine duration and corpus size
|
|
- 2-3 real search queries + retrieved results
|
|
- wake-up context token count
|
|
- whether MCP wiring succeeded
|
|
|
|
## Honest scope boundary
|
|
|
|
This repo artifact does **not** prove live installation on Ezra's host. It makes the work reproducible and testable so the next pass can execute it without guesswork.
|
|
"""
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="Prepare the MemPalace Ezra integration packet")
|
|
parser.add_argument("--hermes-home", default=DEFAULT_HERMES_HOME)
|
|
parser.add_argument("--sessions-dir", default=DEFAULT_SESSIONS_DIR)
|
|
parser.add_argument("--palace-path", default=DEFAULT_PALACE_PATH)
|
|
parser.add_argument("--wing", default=DEFAULT_WING)
|
|
parser.add_argument("--output", default=None)
|
|
parser.add_argument("--json", action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
plan = build_plan(
|
|
{
|
|
"hermes_home": args.hermes_home,
|
|
"sessions_dir": args.sessions_dir,
|
|
"palace_path": args.palace_path,
|
|
"wing": args.wing,
|
|
}
|
|
)
|
|
rendered = json.dumps(plan, indent=2) if args.json else render_markdown(plan)
|
|
|
|
if args.output:
|
|
output_path = Path(args.output).expanduser()
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_text(rendered, encoding="utf-8")
|
|
print(f"MemPalace integration packet written to {output_path}")
|
|
else:
|
|
print(rendered)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|