mirror of
https://github.com/Heretek-AI/openclaw.git
synced 2026-08-27 09:01:15 -04:00
536bba8912
- Replace stub lib/triad-matrix-client.js with full matrix-js-sdk implementation - Add TriadMatrixClient class with connect, startSync, sendMessage, getMessages, joinRoom, getOrCreateRoom, inviteUser - Add test-matrix-client.mjs test script - Add tabula-backup skill for hourly node state backup to Tabula_Myriad repo - Update MEMORY.md with corrected triad state The Matrix client enables: - Node auth as users (not bots) - Consensus room #consensus:silica-animus.local - Direct TM1<->TM2<->TM3 communication via Dendrite homeserver TM-1 authority commit
189 lines
6.3 KiB
JavaScript
189 lines
6.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* @file test-matrix-client.mjs
|
|
* @description Test script for TriadMatrixClient
|
|
*
|
|
* Tests:
|
|
* 1. Connect to Matrix homeserver as @tm1:silica-animus.local
|
|
* 2. Join or create the consensus room #consensus:silica-animus.local
|
|
* 3. Send a test message "TM-1 matrix client test"
|
|
* 4. Verify the message appears in the room
|
|
*
|
|
* Usage: node scripts/test-matrix-client.mjs
|
|
*/
|
|
|
|
import { readFileSync, existsSync } from "fs";
|
|
import { join, dirname } from "path";
|
|
import { fileURLToPath } from "url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
|
// Configuration
|
|
const CONFIG = {
|
|
homeserver: process.env.MATRIX_HOMESERVER || "http://127.0.0.1:8008",
|
|
userId: process.env.MATRIX_USER_ID || "@tm1:silica-animus.local",
|
|
consensusRoomAlias: process.env.MATRIX_CONSENSUS_ROOM || "#consensus:silica-animus.local",
|
|
testMessage: "TM-1 matrix client test",
|
|
tokenPath: join(__dirname, "..", ".secure", "matrix", "tm1.token"),
|
|
};
|
|
|
|
console.log("=".repeat(60));
|
|
console.log("TriadMatrixClient Test Script");
|
|
console.log("=".repeat(60));
|
|
console.log("Config:");
|
|
console.log(` homeserver: ${CONFIG.homeserver}`);
|
|
console.log(` userId: ${CONFIG.userId}`);
|
|
console.log(` consensusRoom: ${CONFIG.consensusRoomAlias}`);
|
|
console.log(` testMessage: ${CONFIG.testMessage}`);
|
|
console.log("=".repeat(60));
|
|
|
|
// Import the client
|
|
const { TriadMatrixClient } = await import("../lib/triad-matrix-client.js");
|
|
|
|
/**
|
|
* Load access token from .secure/matrix/tm1.token
|
|
*/
|
|
function loadToken() {
|
|
const tokenFile = CONFIG.tokenPath;
|
|
console.log(`\n[1] Loading token from ${tokenFile}`);
|
|
|
|
if (!existsSync(tokenFile)) {
|
|
throw new Error(
|
|
`Token file not found: ${tokenFile}. Run the login flow first to obtain a token.`,
|
|
);
|
|
}
|
|
|
|
const token = readFileSync(tokenFile, "utf8").trim();
|
|
if (!token) {
|
|
throw new Error("Token file is empty");
|
|
}
|
|
console.log(` Token loaded (${token.length} chars)`);
|
|
return token;
|
|
}
|
|
|
|
/**
|
|
* Test the Matrix client
|
|
*/
|
|
async function runTests() {
|
|
const client = new TriadMatrixClient();
|
|
let token = null;
|
|
|
|
try {
|
|
// Step 1: Load token and connect
|
|
console.log("\n[2] Connecting to Matrix homeserver...");
|
|
token = loadToken();
|
|
|
|
await client.connect(CONFIG.homeserver, CONFIG.userId, token);
|
|
console.log(` Connected: ${client.connected}`);
|
|
|
|
if (!client.connected) {
|
|
throw new Error("Failed to connect");
|
|
}
|
|
|
|
// Step 2: Start sync to receive updates
|
|
console.log("\n[3] Starting sync...");
|
|
await client.startSync({
|
|
onMessage: (roomId, event) => {
|
|
console.log(` [INCOMING] ${event.sender}: ${event.content?.body}`);
|
|
},
|
|
onInvite: (roomId, inviter) => {
|
|
console.log(` [INVITE] ${inviter} invited you to ${roomId}`);
|
|
},
|
|
});
|
|
console.log(" Sync started");
|
|
|
|
// Step 3: Get or create the consensus room
|
|
console.log("\n[4] Getting/creating consensus room...");
|
|
const consensusRoomId = await client.getOrCreateRoom(CONFIG.consensusRoomAlias, {
|
|
name: "Triad Consensus Room",
|
|
topic: "Official triad node consensus coordination — 2-of-3 quorum required",
|
|
});
|
|
console.log(` Consensus room ID: ${consensusRoomId}`);
|
|
|
|
// Step 4: Join the room (if not already joined)
|
|
console.log("\n[5] Joining consensus room...");
|
|
try {
|
|
const joinedRoomId = await client.joinRoom(CONFIG.consensusRoomAlias);
|
|
console.log(` Joined room: ${joinedRoomId}`);
|
|
} catch (err) {
|
|
console.log(` Join result: ${err.message} (may already be joined)`);
|
|
}
|
|
|
|
// Step 5: Get current messages before sending
|
|
console.log("\n[6] Getting current messages in room...");
|
|
const beforeMessages = await client.getMessages(CONFIG.consensusRoomAlias, 5);
|
|
console.log(` Current message count: ${beforeMessages.length}`);
|
|
beforeMessages.forEach((msg, i) => {
|
|
console.log(
|
|
` [${i + 1}] ${msg.sender}: ${msg.body} (${new Date(msg.timestamp).toISOString()})`,
|
|
);
|
|
});
|
|
|
|
// Step 6: Send the test message
|
|
console.log("\n[7] Sending test message...");
|
|
console.log(` Message: "${CONFIG.testMessage}"`);
|
|
const sendResult = await client.sendMessage(CONFIG.consensusRoomAlias, CONFIG.testMessage);
|
|
console.log(` Send result: eventId=${sendResult.eventId}, timestamp=${sendResult.timestamp}`);
|
|
|
|
if (!sendResult.eventId) {
|
|
throw new Error("Send did not return an eventId");
|
|
}
|
|
|
|
// Step 7: Wait a moment for sync to process the message
|
|
console.log("\n[8] Waiting for sync to process...");
|
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
|
|
// Step 8: Verify the message appears in the room
|
|
console.log("\n[9] Verifying message was sent...");
|
|
const afterMessages = await client.getMessages(CONFIG.consensusRoomAlias, 5);
|
|
console.log(` Message count after send: ${afterMessages.length}`);
|
|
|
|
const ourMessage = afterMessages.find(
|
|
(msg) => msg.body === CONFIG.testMessage && msg.sender === CONFIG.userId,
|
|
);
|
|
|
|
if (ourMessage) {
|
|
console.log(` ✓ Message verified!`);
|
|
console.log(` eventId: ${ourMessage.eventId}`);
|
|
console.log(` sender: ${ourMessage.sender}`);
|
|
console.log(` body: ${ourMessage.body}`);
|
|
console.log(` timestamp: ${new Date(ourMessage.timestamp).toISOString()}`);
|
|
} else {
|
|
console.log(` ✗ Message not found in recent messages`);
|
|
console.log(` Recent messages:`);
|
|
afterMessages.forEach((msg, i) => {
|
|
console.log(` [${i + 1}] ${msg.sender}: ${msg.body}`);
|
|
});
|
|
}
|
|
|
|
// Step 9: List all joined rooms
|
|
console.log("\n[10] Listing joined rooms...");
|
|
const rooms = client.getJoinedRooms();
|
|
console.log(` Joined rooms: ${rooms.length}`);
|
|
rooms.forEach((room) => {
|
|
console.log(` - ${room.name} (${room.roomId}) - ${room.memberCount} members`);
|
|
});
|
|
|
|
console.log("\n" + "=".repeat(60));
|
|
console.log("TEST RESULT: SUCCESS");
|
|
console.log("=".repeat(60));
|
|
} catch (err) {
|
|
console.error("\n" + "=".repeat(60));
|
|
console.error("TEST RESULT: FAILED");
|
|
console.error(`Error: ${err.message}`);
|
|
console.error("=".repeat(60));
|
|
process.exitCode = 1;
|
|
} finally {
|
|
// Cleanup
|
|
console.log("\n[11] Disconnecting...");
|
|
await client.disconnect();
|
|
console.log(" Disconnected");
|
|
}
|
|
}
|
|
|
|
// Run the tests
|
|
runTests().catch((err) => {
|
|
console.error("Unhandled error:", err);
|
|
process.exit(1);
|
|
});
|