openclaw-elys 1.4.7 → 1.5.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.
- package/README.md +2 -5
- package/dist/src/monitor.js +2 -2
- package/dist/src/mqtt-client.d.ts +2 -2
- package/dist/src/mqtt-client.js +14 -12
- package/dist/src/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,12 +8,9 @@ Elys App 的 OpenClaw 频道插件 — 将本地 OpenClaw 智能体连接到 Ely
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
# 1. Install the plugin / 安装插件
|
|
11
|
-
openclaw plugins install openclaw-elys
|
|
11
|
+
openclaw plugins install openclaw-elys@latest
|
|
12
12
|
|
|
13
|
-
# 2.
|
|
14
|
-
openclaw gateway restart
|
|
15
|
-
|
|
16
|
-
# 3. Register device / 注册设备
|
|
13
|
+
# 2. Register device / 注册设备
|
|
17
14
|
npx openclaw-elys@latest setup <gateway_url> <register_token>
|
|
18
15
|
```
|
|
19
16
|
|
package/dist/src/monitor.js
CHANGED
|
@@ -65,7 +65,7 @@ export async function monitorElysProvider(opts) {
|
|
|
65
65
|
fullText += payload.text;
|
|
66
66
|
seq++;
|
|
67
67
|
const done = info.kind === "final";
|
|
68
|
-
mqttClient.publishStreamChunk(cmd.id, payload.text, seq, done);
|
|
68
|
+
mqttClient.publishStreamChunk(cmd.id, payload.text, seq, done, cmd.reply_to);
|
|
69
69
|
if (info.kind === "block") {
|
|
70
70
|
log(`[elys] stream chunk #${seq}: ${payload.text.slice(0, 80)}...`);
|
|
71
71
|
}
|
|
@@ -75,7 +75,7 @@ export async function monitorElysProvider(opts) {
|
|
|
75
75
|
}
|
|
76
76
|
else if (info.kind === "final") {
|
|
77
77
|
seq++;
|
|
78
|
-
mqttClient.publishStreamChunk(cmd.id, "", seq, true);
|
|
78
|
+
mqttClient.publishStreamChunk(cmd.id, "", seq, true, cmd.reply_to);
|
|
79
79
|
log(`[elys] final reply delivered (empty)`);
|
|
80
80
|
}
|
|
81
81
|
},
|
|
@@ -11,14 +11,14 @@ export declare class ElysDeviceMQTTClient {
|
|
|
11
11
|
private log;
|
|
12
12
|
private consecutiveFailures;
|
|
13
13
|
private static readonly MAX_FAILURES_BEFORE_REVOKE_WARNING;
|
|
14
|
+
private commandQueue;
|
|
14
15
|
constructor(credentials: DeviceCredentials, log?: (...args: unknown[]) => void);
|
|
15
16
|
setCommandHandler(handler: CommandHandler): void;
|
|
16
17
|
connect(abortSignal?: AbortSignal): Promise<void>;
|
|
17
18
|
disconnect(): void;
|
|
18
19
|
/** Send a stream chunk (for streaming AI responses) */
|
|
19
|
-
publishStreamChunk(commandId: string, chunk: string, seq: number, done: boolean): void;
|
|
20
|
+
publishStreamChunk(commandId: string, chunk: string, seq: number, done: boolean, replyTo?: string): void;
|
|
20
21
|
private handleMessage;
|
|
21
22
|
private publishAck;
|
|
22
|
-
private publishResult;
|
|
23
23
|
private publish;
|
|
24
24
|
}
|
package/dist/src/mqtt-client.js
CHANGED
|
@@ -10,6 +10,7 @@ export class ElysDeviceMQTTClient {
|
|
|
10
10
|
log;
|
|
11
11
|
consecutiveFailures = 0;
|
|
12
12
|
static MAX_FAILURES_BEFORE_REVOKE_WARNING = 3;
|
|
13
|
+
commandQueue = Promise.resolve();
|
|
13
14
|
constructor(credentials, log) {
|
|
14
15
|
this.credentials = credentials;
|
|
15
16
|
this.log = log ?? console.log;
|
|
@@ -42,7 +43,8 @@ export class ElysDeviceMQTTClient {
|
|
|
42
43
|
});
|
|
43
44
|
});
|
|
44
45
|
this.client.on("message", (_topic, payload) => {
|
|
45
|
-
|
|
46
|
+
// Serial queue: commands are processed one at a time in arrival order
|
|
47
|
+
this.commandQueue = this.commandQueue.then(() => this.handleMessage(payload), () => this.handleMessage(payload)).catch((err) => {
|
|
46
48
|
this.log("[elys] error handling message:", err);
|
|
47
49
|
});
|
|
48
50
|
});
|
|
@@ -102,7 +104,7 @@ export class ElysDeviceMQTTClient {
|
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
/** Send a stream chunk (for streaming AI responses) */
|
|
105
|
-
publishStreamChunk(commandId, chunk, seq, done) {
|
|
107
|
+
publishStreamChunk(commandId, chunk, seq, done, replyTo) {
|
|
106
108
|
const msg = {
|
|
107
109
|
id: commandId,
|
|
108
110
|
type: "stream",
|
|
@@ -111,7 +113,7 @@ export class ElysDeviceMQTTClient {
|
|
|
111
113
|
seq,
|
|
112
114
|
done,
|
|
113
115
|
};
|
|
114
|
-
this.publish(msg);
|
|
116
|
+
this.publish(msg, replyTo);
|
|
115
117
|
}
|
|
116
118
|
async handleMessage(payload) {
|
|
117
119
|
const raw = JSON.parse(payload.toString());
|
|
@@ -120,23 +122,25 @@ export class ElysDeviceMQTTClient {
|
|
|
120
122
|
return;
|
|
121
123
|
}
|
|
122
124
|
this.log(`[elys] received command: ${raw.command} (id: ${raw.id})`);
|
|
123
|
-
//
|
|
125
|
+
// ACK always goes to shared upstream topic (any gateway instance can process it)
|
|
124
126
|
this.publishAck(raw.id);
|
|
127
|
+
// Result/stream goes to reply_to if present (routes to the specific gateway instance)
|
|
128
|
+
const replyTo = raw.reply_to;
|
|
125
129
|
// Execute command
|
|
126
130
|
if (this.commandHandler) {
|
|
127
131
|
try {
|
|
128
132
|
const result = await this.commandHandler(raw);
|
|
129
|
-
this.
|
|
133
|
+
this.publish(result, replyTo);
|
|
130
134
|
}
|
|
131
135
|
catch (err) {
|
|
132
136
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
133
|
-
this.
|
|
137
|
+
this.publish({
|
|
134
138
|
id: raw.id,
|
|
135
139
|
type: "result",
|
|
136
140
|
timestamp: Date.now() / 1000,
|
|
137
141
|
status: "error",
|
|
138
142
|
error: errMsg,
|
|
139
|
-
});
|
|
143
|
+
}, replyTo);
|
|
140
144
|
}
|
|
141
145
|
}
|
|
142
146
|
}
|
|
@@ -146,15 +150,13 @@ export class ElysDeviceMQTTClient {
|
|
|
146
150
|
type: "ack",
|
|
147
151
|
timestamp: Math.floor(Date.now() / 1000),
|
|
148
152
|
};
|
|
153
|
+
// ACK always to default upstream topic (shared subscription)
|
|
149
154
|
this.publish(msg);
|
|
150
155
|
}
|
|
151
|
-
|
|
152
|
-
this.publish(msg);
|
|
153
|
-
}
|
|
154
|
-
publish(msg) {
|
|
156
|
+
publish(msg, replyTo) {
|
|
155
157
|
if (!this.client)
|
|
156
158
|
return;
|
|
157
|
-
const topic = `elys/up/${this.credentials.deviceId}`;
|
|
159
|
+
const topic = replyTo || `elys/up/${this.credentials.deviceId}`;
|
|
158
160
|
this.client.publish(topic, JSON.stringify(msg), { qos: 1 }, (err) => {
|
|
159
161
|
if (err) {
|
|
160
162
|
this.log(`[elys] failed to publish to ${topic}:`, err);
|
package/dist/src/types.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface CommandMessage extends MQTTBaseMessage {
|
|
|
24
24
|
type: "command";
|
|
25
25
|
command: string;
|
|
26
26
|
args?: Record<string, unknown>;
|
|
27
|
+
/** If set, device should publish result/stream to this topic instead of elys/up/{device_id} */
|
|
28
|
+
reply_to?: string;
|
|
27
29
|
}
|
|
28
30
|
export interface AckMessage extends MQTTBaseMessage {
|
|
29
31
|
type: "ack";
|