Compare commits

..

2 Commits

Author SHA1 Message Date
Hermes Agent
de7253dcdf fix: use consistent fallback for pickle_key derivation
Address review: _pickle_key now uses _acct_id (which has the 'hermes'
fallback) instead of raw self._user_id, so both values stay consistent
when user_id is empty.
2026-04-11 17:26:17 +00:00
Hermes Agent
050f496816 fix(matrix): pass required args to MemoryCryptoStore for mautrix ≥0.21
MemoryCryptoStore.__init__() now requires account_id and pickle_key
positional arguments as of mautrix 0.21. The migration from matrix-nio
(commit 1850747) didn't account for this, causing E2EE initialization
to fail with:

  MemoryCryptoStore.__init__() missing 2 required positional arguments:
  'account_id' and 'pickle_key'

Pass self._user_id as account_id and derive pickle_key from the same
user_id:device_id pair already used for the on-disk HMAC signature.

Update the test stub to accept the new parameters.

Fixes #7803
2026-04-11 17:03:38 +00:00
3 changed files with 21 additions and 16 deletions

View File

@@ -352,7 +352,16 @@ class MatrixAdapter(BasePlatformAdapter):
from mautrix.crypto import OlmMachine
from mautrix.crypto.store import MemoryCryptoStore
crypto_store = MemoryCryptoStore()
# account_id and pickle_key are required by mautrix ≥0.21.
# Use the Matrix user ID as account_id for stable identity.
# pickle_key secures in-memory serialisation; derive from
# the same user_id:device_id pair used for the on-disk HMAC.
_acct_id = self._user_id or "hermes"
_pickle_key = f"{_acct_id}:{self._device_id}"
crypto_store = MemoryCryptoStore(
account_id=_acct_id,
pickle_key=_pickle_key,
)
# Restore persisted crypto state from a previous run.
# Uses HMAC to verify integrity before unpickling.

View File

@@ -1890,11 +1890,11 @@ class Migrator:
if defaults.get("thinkingDefault"):
# Map OpenClaw thinking -> Hermes reasoning_effort
thinking = defaults["thinkingDefault"]
if thinking in ("always", "high", "xhigh"):
if thinking in ("always", "high"):
agent_cfg["reasoning_effort"] = "high"
elif thinking in ("auto", "medium", "adaptive"):
elif thinking in ("auto", "medium"):
agent_cfg["reasoning_effort"] = "medium"
elif thinking in ("off", "low", "none", "minimal"):
elif thinking in ("off", "low", "none"):
agent_cfg["reasoning_effort"] = "low"
changes = True
@@ -2099,14 +2099,10 @@ class Migrator:
f"Provider '{prov_name}' already exists")
continue
api_type = prov_cfg.get("apiType") or prov_cfg.get("api") or prov_cfg.get("type") or "openai"
api_type = prov_cfg.get("apiType") or prov_cfg.get("type") or "openai"
api_mode_map = {
"openai": "chat_completions",
"openai-completions": "chat_completions",
"openai-responses": "chat_completions",
"anthropic": "anthropic_messages",
"anthropic-messages": "anthropic_messages",
"google-generative-ai": "chat_completions",
"cohere": "chat_completions",
}
entry = {
@@ -2146,7 +2142,7 @@ class Migrator:
# Extended channel token/allowlist mapping
CHANNEL_ENV_MAP = {
"matrix": {"token": "MATRIX_ACCESS_TOKEN", "tokenField": "accessToken", "allowFrom": "MATRIX_ALLOWED_USERS",
"matrix": {"token": "MATRIX_ACCESS_TOKEN", "allowFrom": "MATRIX_ALLOWED_USERS",
"extras": {"homeserverUrl": "MATRIX_HOMESERVER_URL", "userId": "MATRIX_USER_ID"}},
"mattermost": {"token": "MATTERMOST_BOT_TOKEN", "allowFrom": "MATTERMOST_ALLOWED_USERS",
"extras": {"url": "MATTERMOST_URL", "teamId": "MATTERMOST_TEAM_ID"}},
@@ -2165,11 +2161,9 @@ class Migrator:
continue
# Extract tokens
token_field = ch_mapping.get("tokenField", "botToken")
ch_token = ch_cfg.get(token_field)
if ch_mapping.get("token") and ch_token and self.migrate_secrets:
self._set_env_var(ch_mapping["token"], str(ch_token),
f"channels.{ch_name}.{token_field}")
if ch_mapping.get("token") and ch_cfg.get("botToken") and self.migrate_secrets:
self._set_env_var(ch_mapping["token"], ch_cfg["botToken"],
f"channels.{ch_name}.botToken")
if ch_mapping.get("allowFrom") and ch_cfg.get("allowFrom"):
allow_val = ch_cfg["allowFrom"]
if isinstance(allow_val, list):

View File

@@ -157,7 +157,9 @@ def _make_fake_mautrix():
mautrix_crypto_store = types.ModuleType("mautrix.crypto.store")
class MemoryCryptoStore:
pass
def __init__(self, account_id="", pickle_key=""):
self.account_id = account_id
self.pickle_key = pickle_key
mautrix_crypto_store.MemoryCryptoStore = MemoryCryptoStore