854ae41f65
Round out the pi bring-up story so a fresh machine can reach a working pi+mempalace install with just `git clone && ./install.sh`: - extensions/pi/keybindings.json: generic mosh/tmux newline fix (shift+enter, ctrl+j, alt+j). Safe on any machine — not region/account-specific. Symlinked into ~/.pi/agent/. - extensions/pi/settings.example.json: template for `settings.json` so pi can start without --provider/--model. NOT symlinked — pi rewrites settings.json at runtime (lastChangelogVersion bumps), which would dirty the repo. Installer prints the cp + edit hint. - install.sh: new install_pi_keybindings + uninstall mirror; new check_pi_settings probe (warns if settings.json missing); new check_aws_env probe (warns if AWS_PROFILE/AWS_REGION unset and settings.json selects amazon-bedrock). All new steps gated on pi being installed (~/.pi/agent/extensions/ exists). - extensions/pi/README.md: documents keybindings rationale, settings bootstrap, and the recommended ~/.config/pi/.env + ~/.oh-my-zsh/custom/pi-env.zsh env layout (paired with the myconfigs commit 884e329 that split AWS vars out of ~/.config/opencode/.env). Verified on tor-ms22: full install → uninstall → reinstall cycle, new shell loads AWS_PROFILE/AWS_REGION from the new pi-env.zsh hook. Works on macOS and Linux (plain ln -s, POSIX bash).
144 lines
5.9 KiB
Markdown
144 lines
5.9 KiB
Markdown
# pi ↔ MemPalace extension
|
|
|
|
The canonical source of `~/.pi/agent/extensions/mempalace.ts` — the bridge
|
|
that wires the [MemPalace](https://github.com/MemPalace/mempalace) MCP
|
|
server into the [pi coding-agent](https://github.com/mariozechner/pi-coding-agent)
|
|
harness.
|
|
|
|
`install.sh` at the repo root symlinks `mempalace.ts` from this directory
|
|
into `~/.pi/agent/extensions/` so the live file on every machine tracks
|
|
version control. Works on macOS and Linux (the extension itself is plain
|
|
Node / TypeScript; the symlink is a POSIX `ln -s`).
|
|
|
|
---
|
|
|
|
## What it does
|
|
|
|
1. **Spawns `mempalace-mcp`** as a subprocess and does the MCP stdio
|
|
JSON-RPC handshake (`initialize` + `notifications/initialized` +
|
|
`tools/list`).
|
|
2. **Registers each MCP tool** as a pi tool with its real `inputSchema`
|
|
passed through via `Type.Unsafe(...)` (see gotcha below).
|
|
3. **Wake-up auto-injection** (`before_agent_start`, one-shot per fresh
|
|
session): calls `mempalace_status` + `mempalace_diary_read` and
|
|
injects the result as a `mempalace-wakeup` system message so the
|
|
agent orients itself the way `~/.agents/skills/mempalace/SKILL.md`
|
|
describes. Skipped on resume/fork (context is already in the thread).
|
|
4. **Manual wind-down** via a `/mempalace-diary [topic]` slash command:
|
|
sends a prompt asking the LLM to call `mempalace_diary_write` with
|
|
an AAAK-formatted entry summarizing the session. Not fully auto
|
|
because pi sessions are typically short/tactical and
|
|
`session_shutdown` fires too late to drive another LLM turn.
|
|
|
|
## Fail-soft
|
|
|
|
If `mempalace-mcp` can't be spawned (PATH missing, binary crashes at
|
|
startup, …) the extension logs to stderr and returns early. pi keeps
|
|
working without palace tools rather than refusing to start.
|
|
|
|
## Identity
|
|
|
|
`agent_name` for diary calls comes from `$MEMPALACE_AGENT_NAME`, defaulting
|
|
to `"pi"`. First diary write against that identity creates `wing_<name>`
|
|
in the palace. Set the env var if you want to run pi under a distinct
|
|
identity on a given machine (e.g. `pi-laptop` vs `pi-server`).
|
|
|
|
## Debugging
|
|
|
|
- `MEMPALACE_EXT_DEBUG=1` — surface `mempalace-mcp` stderr into pi's
|
|
stderr. Without this, stderr is drained silently so a misbehaving
|
|
server doesn't flood the TUI.
|
|
- If a tool call fails with a generic "Internal tool error", spawn
|
|
`mempalace-mcp` manually with raw JSON-RPC on stdin to read the
|
|
server-side error — much faster than guessing.
|
|
|
|
## The `Type.Unsafe` gotcha
|
|
|
|
Earlier versions of this extension registered every MCP tool with
|
|
`parameters: Type.Object({}, { additionalProperties: true })`, which
|
|
discarded each tool's real `inputSchema`. The LLM then saw no parameter
|
|
names and had to guess, leading to bugs like `mempalace_diary_read`
|
|
being called with `agent=` instead of the required `agent_name=` and
|
|
crashing the Python server with `TypeError: missing 1 required
|
|
positional argument`.
|
|
|
|
The fix (≈ lines 160-170) is to wrap the incoming JSON Schema with
|
|
`Type.Unsafe<...>(tool.inputSchema)`. TypeBox schemas are plain JSON
|
|
Schema at runtime plus a `Symbol` marker, so wrapping an
|
|
externally-sourced schema with `Unsafe` is sufficient — no conversion
|
|
to a full TypeBox tree is needed, and the LLM now sees every tool's
|
|
real parameter names.
|
|
|
|
If you ever need to re-loosen the schema for debugging, fall back to
|
|
the `Type.Object({}, { additionalProperties: true })` default only for
|
|
that specific tool, not globally.
|
|
|
|
## Keybindings (mosh/tmux newline fix)
|
|
|
|
`keybindings.json` is symlinked so edits flow through git. Default:
|
|
|
|
```json
|
|
{
|
|
"tui.input.newLine": ["shift+enter", "ctrl+j", "alt+j"]
|
|
}
|
|
```
|
|
|
|
Rationale: when pi runs over `kitty → mosh → tmux`, shift+enter doesn't
|
|
forward cleanly (mosh uses vt220-ish emulation, no kitty-keyboard-protocol
|
|
or csi-u extended keys). `ctrl+j` and `alt+j` pass through as plain
|
|
control/meta bytes and give you reliable newline insertion.
|
|
|
|
## Settings template (start pi without `--model`)
|
|
|
|
`settings.example.json` is a template — **not symlinked**. pi rewrites
|
|
its `settings.json` at runtime (`lastChangelogVersion` bumps on upgrade),
|
|
which would dirty a symlinked repo file. Instead, bootstrap with:
|
|
|
|
```bash
|
|
cp /path/to/mempalace-toolkit/extensions/pi/settings.example.json \
|
|
~/.pi/agent/settings.json
|
|
$EDITOR ~/.pi/agent/settings.json
|
|
```
|
|
|
|
The Bedrock inference-profile prefix on model IDs (`eu.`, `us.`) is
|
|
**region-specific** and must match `AWS_REGION` in `~/.config/pi/.env`.
|
|
For a bare Anthropic provider (non-Bedrock) drop the prefix entirely
|
|
and use `anthropic:claude-...`. Run `pi --list-models` to confirm what
|
|
your credentials can actually invoke.
|
|
|
|
`install.sh` warns (non-fatal) if `settings.json` is missing.
|
|
|
|
## Environment setup
|
|
|
|
pi with `defaultProvider=amazon-bedrock` needs `AWS_PROFILE` and
|
|
`AWS_REGION` exported into the shell that launches it. Recommended
|
|
layout (matches the tor-ms22 dotfiles pattern):
|
|
|
|
```
|
|
~/.config/pi/.env ← AWS_PROFILE=..., AWS_REGION=...
|
|
(git-crypt encrypted in dotfiles repo)
|
|
~/.oh-my-zsh/custom/pi-env.zsh ← set -a; source ~/.config/pi/.env; set +a
|
|
```
|
|
|
|
Historical note: these vars used to live under a `# Environment variables
|
|
for pi` block inside `~/.config/opencode/.env`. Split out 2026-05-05 so
|
|
each tool owns its own env file. `install.sh` runs a `check_aws_env`
|
|
probe that warns if the vars are missing and points back here.
|
|
|
|
## File layout
|
|
|
|
```
|
|
mempalace-toolkit/
|
|
└── extensions/
|
|
└── pi/
|
|
├── README.md ← this file
|
|
├── mempalace.ts ← symlinked into ~/.pi/agent/extensions/
|
|
├── keybindings.json ← symlinked into ~/.pi/agent/
|
|
└── settings.example.json ← template; copy + edit into ~/.pi/agent/
|
|
```
|
|
|
|
`install.sh` detects pi by probing for `~/.pi/agent/extensions/` and
|
|
only creates symlinks when that directory exists. On machines without
|
|
pi the files stay dormant in the repo. Re-runs are idempotent (same
|
|
pattern as `bin/` and `SKILL.md`).
|