clawnexus 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ export interface RelayConnectorOptions {
8
8
  autoAccept?: boolean;
9
9
  }
10
10
  export declare class RelayConnector extends EventEmitter {
11
- private readonly options;
11
+ private options;
12
12
  private ws;
13
13
  private state;
14
14
  private rooms;
@@ -17,10 +17,14 @@ export declare class RelayConnector extends EventEmitter {
17
17
  private reconnectTimer;
18
18
  private closed;
19
19
  constructor(options: RelayConnectorOptions);
20
+ /** Update the auth token (e.g. after token refresh). */
21
+ updateAuthToken(token: string): void;
20
22
  /** Connect to the relay and REGISTER this claw_id. */
21
23
  connect(): void;
22
24
  /** Disconnect and stop reconnecting. */
23
25
  disconnect(): void;
26
+ private pendingJoins;
27
+ private lastJoinTarget;
24
28
  /** Initiate a connection to a remote claw_id through the relay. */
25
29
  join(targetClawId: string): void;
26
30
  /** Send an encrypted message to a peer in a room. */
@@ -20,6 +20,10 @@ class RelayConnector extends node_events_1.EventEmitter {
20
20
  this.options = options;
21
21
  this.keyPair = (0, crypto_js_1.generateKeyPair)();
22
22
  }
23
+ /** Update the auth token (e.g. after token refresh). */
24
+ updateAuthToken(token) {
25
+ this.options = { ...this.options, authToken: token };
26
+ }
23
27
  /** Connect to the relay and REGISTER this claw_id. */
24
28
  connect() {
25
29
  if (this.state !== "disconnected")
@@ -66,8 +70,12 @@ class RelayConnector extends node_events_1.EventEmitter {
66
70
  this.ws?.close();
67
71
  this.cleanup();
68
72
  }
73
+ // Tracks target claw_id for pending JOIN requests
74
+ pendingJoins = new Map(); // target_claw_id → target_claw_id (for JOINED room_id lookup)
75
+ lastJoinTarget = null;
69
76
  /** Initiate a connection to a remote claw_id through the relay. */
70
77
  join(targetClawId) {
78
+ this.lastJoinTarget = targetClawId;
71
79
  this.send({
72
80
  type: "JOIN",
73
81
  claw_id: this.options.clawId,
@@ -78,8 +86,10 @@ class RelayConnector extends node_events_1.EventEmitter {
78
86
  /** Send an encrypted message to a peer in a room. */
79
87
  sendData(roomId, plaintext) {
80
88
  const room = this.rooms.get(roomId);
81
- if (!room || !room.session_key)
89
+ if (!room || !room.session_key) {
90
+ console.log(`[clawnexus] [Relay] sendData failed: room=${roomId} exists=${!!room} hasKey=${!!room?.session_key}`);
82
91
  return false;
92
+ }
83
93
  const payload = (0, crypto_js_1.encrypt)(room.session_key, plaintext);
84
94
  this.send({ type: "DATA", room_id: roomId, payload });
85
95
  return true;
@@ -98,6 +108,7 @@ class RelayConnector extends node_events_1.EventEmitter {
98
108
  room_id: r.room_id,
99
109
  peer_claw_id: r.peer_claw_id,
100
110
  state: r.state,
111
+ has_session_key: !!r.session_key,
101
112
  })),
102
113
  };
103
114
  }
@@ -139,7 +150,7 @@ class RelayConnector extends node_events_1.EventEmitter {
139
150
  // We are the initiator — create room entry
140
151
  this.rooms.set(msg.room_id, {
141
152
  room_id: msg.room_id,
142
- peer_claw_id: "", // will be known after key exchange
153
+ peer_claw_id: this.lastJoinTarget ?? "",
143
154
  state: "active",
144
155
  });
145
156
  // Send our public key
@@ -179,9 +190,13 @@ class RelayConnector extends node_events_1.EventEmitter {
179
190
  this.emit("data", msg.room_id, plaintext);
180
191
  }
181
192
  catch {
182
- this.emit("error", new Error("Failed to decrypt message"));
193
+ // Decrypt failed — log and skip, do not emit "error" (would crash if no listener)
194
+ console.log(`[clawnexus] [Relay] Failed to decrypt message in room ${msg.room_id} — skipping`);
183
195
  }
184
196
  }
197
+ else {
198
+ console.log(`[clawnexus] [Relay] DATA in room ${msg.room_id} — no session_key yet, dropping`);
199
+ }
185
200
  break;
186
201
  }
187
202
  case "PEER_LEFT": {
package/dist/types.d.ts CHANGED
@@ -1,3 +1,16 @@
1
+ import type { AgentSkill } from "./a2a/card.js";
2
+ export interface RemoteCard {
3
+ skills: AgentSkill[];
4
+ capabilities?: {
5
+ streaming?: boolean;
6
+ pushNotifications?: boolean;
7
+ stateTransitionHistory?: boolean;
8
+ };
9
+ input_modes?: string[];
10
+ output_modes?: string[];
11
+ card_url: string;
12
+ fetched_at: string;
13
+ }
1
14
  export type ClawImplementation = "openclaw" | "goclaw" | "zeroclaw" | "picoclaw" | "nanoclaw" | "nanobot" | "openfang" | "unknown";
2
15
  export interface ClawInstance {
3
16
  agent_id: string;
@@ -20,6 +33,7 @@ export interface ClawInstance {
20
33
  claw_name?: string;
21
34
  owner_pubkey?: string;
22
35
  implementation?: ClawImplementation;
36
+ remote_card?: RemoteCard;
23
37
  labels?: Record<string, string>;
24
38
  }
25
39
  export interface Connectivity {
@@ -39,7 +53,7 @@ export interface UnreachableInstance {
39
53
  discovered_at: string;
40
54
  }
41
55
  export interface RegistryFile {
42
- schema_version: "2" | "3" | "4" | "5";
56
+ schema_version: "2" | "3" | "4" | "5" | "6";
43
57
  updated_at: string;
44
58
  instances: ClawInstance[];
45
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawnexus",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "ClawNexus daemon and CLI — AI instance registry for OpenClaw",
5
5
  "license": "MIT",
6
6
  "author": "alan-silverstreams <alan@silverstream.tech>",