cleanup: remove clawd/openclaw references, fix permissions, add architecture docs

- Replace all ~/clawd and ~/.clawdbot paths with ~/echo-core equivalents
  in tools (git_commit, ralph_prd_generator, backup_config, lead-gen)
- Update personality files: TOOLS.md repo/paths, AGENTS.md security audit cmd
- Migrate HANDOFF.md architectural decisions to docs/architecture.md
- Tighten credentials/ dir to 700, add to .gitignore
- Add .claude/ and *.pid to .gitignore
- Various adapter, router, and session improvements from prior work

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
MoltBot Service
2026-02-14 21:44:13 +00:00
parent d585c85081
commit 5928077646
35 changed files with 666 additions and 790 deletions

View File

@@ -15,6 +15,7 @@ from src.adapters.whatsapp import (
split_message,
poll_messages,
send_whatsapp,
react_whatsapp,
get_bridge_status,
handle_incoming,
run_whatsapp,
@@ -229,6 +230,41 @@ class TestGetBridgeStatus:
assert result is None
class TestReactWhatsapp:
@pytest.mark.asyncio
async def test_successful_react(self):
client = _mock_client()
client.post.return_value = _mock_httpx_response(json_data={"ok": True})
result = await react_whatsapp(client, "123@s.whatsapp.net", "msg-id-1", "\U0001f440")
assert result is True
client.post.assert_called_once()
sent_json = client.post.call_args[1]["json"]
assert sent_json == {"to": "123@s.whatsapp.net", "id": "msg-id-1", "emoji": "\U0001f440", "fromMe": False}
@pytest.mark.asyncio
async def test_react_remove(self):
client = _mock_client()
client.post.return_value = _mock_httpx_response(json_data={"ok": True})
result = await react_whatsapp(client, "123@s.whatsapp.net", "msg-id-1", "")
assert result is True
@pytest.mark.asyncio
async def test_react_bridge_error(self):
client = _mock_client()
client.post.side_effect = httpx.ConnectError("bridge down")
result = await react_whatsapp(client, "123@s.whatsapp.net", "msg-id-1", "\U0001f440")
assert result is False
@pytest.mark.asyncio
async def test_react_500(self):
client = _mock_client()
client.post.return_value = _mock_httpx_response(
status_code=500, json_data={"ok": False}
)
result = await react_whatsapp(client, "123@s.whatsapp.net", "msg-id-1", "\U0001f440")
assert result is False
# --- Message handler ---
@@ -363,6 +399,78 @@ class TestHandleIncoming:
sent_json = client.post.call_args[1]["json"]
assert "Sorry" in sent_json["text"]
@pytest.mark.asyncio
async def test_reaction_flow(self, _set_owned):
"""Eyes reaction added on receipt and removed after response."""
client = _mock_client()
client.post.return_value = _mock_httpx_response(json_data={"ok": True})
msg = {
"from": "5511999990000@s.whatsapp.net",
"text": "Hello",
"pushName": "Owner",
"isGroup": False,
"id": "msg-abc-123",
}
with patch("src.adapters.whatsapp.route_message", return_value=("Hi!", False)):
await handle_incoming(msg, client)
# Should have 3 post calls: react 👀, send response, react "" (remove)
assert client.post.call_count == 3
calls = client.post.call_args_list
# First call: eyes reaction
react_json = calls[0][1]["json"]
assert react_json["emoji"] == "\U0001f440"
assert react_json["id"] == "msg-abc-123"
assert react_json["fromMe"] is False
# Second call: actual message
send_json = calls[1][1]["json"]
assert send_json["text"] == "Hi!"
# Third call: remove reaction
unreact_json = calls[2][1]["json"]
assert unreact_json["emoji"] == ""
assert unreact_json["id"] == "msg-abc-123"
assert unreact_json["fromMe"] is False
@pytest.mark.asyncio
async def test_reaction_removed_on_error(self, _set_owned):
"""Eyes reaction removed even when route_message raises."""
client = _mock_client()
client.post.return_value = _mock_httpx_response(json_data={"ok": True})
msg = {
"from": "5511999990000@s.whatsapp.net",
"text": "Hello",
"pushName": "Owner",
"isGroup": False,
"id": "msg-abc-456",
}
with patch("src.adapters.whatsapp.route_message", side_effect=Exception("boom")):
await handle_incoming(msg, client)
# react 👀, send error, react "" (remove) — reaction still removed in finally
calls = client.post.call_args_list
unreact_call = calls[-1][1]["json"]
assert unreact_call["emoji"] == ""
assert unreact_call["id"] == "msg-abc-456"
@pytest.mark.asyncio
async def test_no_reaction_without_message_id(self, _set_owned):
"""No reaction calls when message has no id."""
client = _mock_client()
client.post.return_value = _mock_httpx_response(json_data={"ok": True})
msg = {
"from": "5511999990000@s.whatsapp.net",
"text": "Hello",
"pushName": "Owner",
"isGroup": False,
}
with patch("src.adapters.whatsapp.route_message", return_value=("Hi!", False)):
await handle_incoming(msg, client)
# Only 1 call: send response (no react calls)
client.post.assert_called_once()
@pytest.mark.asyncio
async def test_empty_text_ignored(self, _set_owned):
client = _mock_client()