feat(sdk+cli): bridge peer — forward a topic between two meshes
A bridge holds memberships in two meshes and relays messages on a single topic between them. Federation-lite without a broker-to-broker protocol. SDK additions: - Bridge class (start, stop, EventEmitter for forwarded/dropped/error) - MeshClient.joinTopic / leaveTopic / createTopic methods - Loop prevention: plaintext hop counter prefix __cmh<n>: with maxHops default 2; echo guard via senderPubkey == own session pubkey CLI additions: - claudemesh bridge run <config.yaml> long-lived process - claudemesh bridge init prints config template - Zero-dep YAML parser for the flat bridge config shape The hop prefix is visible in message bodies — minor wart, fixed in v0.3.0 by moving loop tracking into broker primitives. SDK kept as devDependency since Bun bundles it into dist; no impact on npm publish or runtime resolution. Spec: .artifacts/specs/2026-05-02-v0.2.0-scope.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -365,6 +365,32 @@ export class MeshClient extends EventEmitter {
|
||||
this.ws.send(JSON.stringify({ type: "set_status", status }));
|
||||
}
|
||||
|
||||
// --- Topics (v0.2.0) ---
|
||||
// Conversational primitive within a mesh. To receive topic-tagged
|
||||
// messages, you must subscribe via `joinTopic`.
|
||||
|
||||
async createTopic(args: {
|
||||
name: string;
|
||||
description?: string;
|
||||
visibility?: "public" | "private" | "dm";
|
||||
}): Promise<void> {
|
||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
||||
this.ws.send(JSON.stringify({ type: "topic_create", ...args }));
|
||||
}
|
||||
|
||||
async joinTopic(
|
||||
topic: string,
|
||||
role?: "lead" | "member" | "observer",
|
||||
): Promise<void> {
|
||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
||||
this.ws.send(JSON.stringify({ type: "topic_join", topic, role }));
|
||||
}
|
||||
|
||||
async leaveTopic(topic: string): Promise<void> {
|
||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
||||
this.ws.send(JSON.stringify({ type: "topic_leave", topic }));
|
||||
}
|
||||
|
||||
// --- Internals ---
|
||||
|
||||
private makeReqId(): string {
|
||||
|
||||
Reference in New Issue
Block a user