- Plugin manifest (plugin.yaml) with pre_gateway_dispatch + on_session_start hooks - /identity slash command for config management - Honcho injector patch docs (6 lines in plugins/memory/honcho/__init__.py) - Config file at /opt/data/identity-config.json for persistence - Kanban task body convention: context_peer: <name> - Sample config with thierry/catherine mappings Architecture: user-installed plugin (hooks + CLI) + 6-line Honcho bundled plugin change
117 lines
3.7 KiB
Markdown
117 lines
3.7 KiB
Markdown
# Honcho Injector Patch
|
|
|
|
The identity plugin cannot directly inject `runtime_user_peer_name` into
|
|
Honcho from a user-installed hook (the hook system only allows message
|
|
rewrite/skip, not user_id modification). Instead, we add ~6 lines in the
|
|
bundled Honcho plugin's session initialization.
|
|
|
|
## File
|
|
|
|
`plugins/memory/honcho/__init__.py` — line ~362
|
|
|
|
## The change
|
|
|
|
### Before
|
|
|
|
```python
|
|
runtime_user_peer_name=kwargs.get("user_id") or None,
|
|
```
|
|
|
|
### After
|
|
|
|
```python
|
|
runtime_user_peer_name=kwargs.get("user_id") or _resolve_identity_peer(),
|
|
```
|
|
|
|
### Add this function in the same file (or import from the identity plugin)
|
|
|
|
```python
|
|
def _resolve_identity_peer() -> str | None:
|
|
"""Resolve peer name from env vars and identity config.
|
|
|
|
Priority: HERMES_HONCHO_PEER_NAME → kanban task body context_peer
|
|
→ kanban board config → None (falls through to Honcho default).
|
|
"""
|
|
import json, os, sqlite3, re
|
|
from pathlib import Path
|
|
|
|
# 1. Explicit env override
|
|
explicit = os.environ.get("HERMES_HONCHO_PEER_NAME")
|
|
if explicit:
|
|
return explicit
|
|
|
|
# 2. Kanban worker: read task body for context_peer
|
|
task_id = os.environ.get("HERMES_KANBAN_TASK")
|
|
db_path = os.environ.get("HERMES_KANBAN_DB")
|
|
if task_id and db_path:
|
|
db = Path(db_path)
|
|
if db.exists():
|
|
try:
|
|
conn = sqlite3.connect(str(db))
|
|
conn.row_factory = sqlite3.Row
|
|
try:
|
|
row = conn.execute(
|
|
"SELECT body FROM tasks WHERE id = ?", (task_id,)
|
|
).fetchone()
|
|
if row and row["body"]:
|
|
m = re.search(r"context_peer:\s*(\S+)", row["body"])
|
|
if m:
|
|
return m.group(1)
|
|
finally:
|
|
conn.close()
|
|
except Exception:
|
|
pass
|
|
|
|
# 3. Identity config file
|
|
cfg_path = Path("/opt/data/identity-config.json")
|
|
if cfg_path.exists():
|
|
try:
|
|
cfg = json.loads(cfg_path.read_text())
|
|
# Check kanban board config
|
|
board = os.environ.get("HERMES_KANBAN_BOARD")
|
|
if board and board in cfg.get("boards", {}):
|
|
return cfg["boards"][board]
|
|
# Use fallback
|
|
return cfg.get("fallback_peer")
|
|
except Exception:
|
|
pass
|
|
|
|
return None
|
|
```
|
|
|
|
## How it works
|
|
|
|
1. When a **gateway session** starts, `kwargs["user_id"]` carries the platform
|
|
ID (Discord snowflake, Telegram UID). The identity config file maps these
|
|
to canonical peer names. The injector is bypassed — normal flow.
|
|
|
|
2. When a **kanban worker** starts, `kwargs["user_id"]` is None (no gateway).
|
|
The injector kicks in:
|
|
|
|
a. Checks `HERMES_HONCHO_PEER_NAME` env var (set by a future dispatcher
|
|
enhancement or manually).
|
|
|
|
b. Reads the kanban task body from the SQLite database, extracts
|
|
`context_peer: <name>` from the body.
|
|
|
|
c. Falls back to the board-level config from identity-config.json.
|
|
|
|
d. If nothing resolves → returns None → Honcho creates `user-default-*`
|
|
as today (safe fallback).
|
|
|
|
## Why not modify the kanban dispatcher?
|
|
|
|
The kanban dispatcher (`hermes_cli/kanban_db.py:_default_spawn`) is core
|
|
Hermes code. We avoid touching it. Instead, the Honcho injector reads the
|
|
task directly from the kanban DB using env vars that are already set
|
|
(`HERMES_KANBAN_TASK`, `HERMES_KANBAN_DB`, `HERMES_KANBAN_BOARD`).
|
|
|
|
This adds ~10 microseconds to worker startup — negligible.
|
|
|
|
## Compatibility
|
|
|
|
- If the identity plugin is removed, the injector function returns None and
|
|
Honcho behaves exactly as before.
|
|
- If the config file is missing, same safe fallback.
|
|
- No data loss risk.
|