openclaw-elys 1.7.4 → 1.7.5

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.
@@ -30,6 +30,8 @@ export declare class ElysDeviceMQTTClient {
30
30
  private static readonly DEDUP_TTL_MS;
31
31
  private currentAbort;
32
32
  private readonly commandTimeoutMs;
33
+ private isExecuting;
34
+ private pendingCommands;
33
35
  constructor(credentials: DeviceCredentials, log?: (...args: unknown[]) => void, options?: MQTTClientOptions);
34
36
  setCommandHandler(handler: CommandHandler): void;
35
37
  connect(abortSignal?: AbortSignal): Promise<void>;
@@ -38,6 +40,8 @@ export declare class ElysDeviceMQTTClient {
38
40
  publishStreamChunk(commandId: string, chunk: string, seq: number, done: boolean): void;
39
41
  private onMessage;
40
42
  private flushDebounce;
43
+ private startCommand;
44
+ private processPendingCommands;
41
45
  /** Merge multiple buffered commands into one. Joins text args with newline. */
42
46
  private mergeCommands;
43
47
  private executeCommand;
@@ -26,6 +26,9 @@ export class ElysDeviceMQTTClient {
26
26
  // Abort & timeout
27
27
  currentAbort = null;
28
28
  commandTimeoutMs;
29
+ // Sequential execution: queue commands while one is running
30
+ isExecuting = false;
31
+ pendingCommands = [];
29
32
  constructor(credentials, log, options) {
30
33
  this.credentials = credentials;
31
34
  this.log = log ?? console.log;
@@ -170,15 +173,37 @@ export class ElysDeviceMQTTClient {
170
173
  this.debounceTimer = null;
171
174
  if (buffered.length === 0)
172
175
  return;
173
- // 4. Abort previous running command
174
- this.currentAbort?.abort();
175
- this.currentAbort = new AbortController();
176
176
  const merged = this.mergeCommands(buffered);
177
- // 5. Execute (fire-and-forget, errors handled inside)
178
- this.executeCommand(merged, this.currentAbort.signal).catch((err) => {
177
+ if (this.isExecuting) {
178
+ // Queue for after current dispatch completes — OpenClaw processes sequentially
179
+ this.log(`[elys] dispatch busy, queuing command ${merged.id}`);
180
+ this.pendingCommands.push(merged);
181
+ return;
182
+ }
183
+ this.startCommand(merged);
184
+ }
185
+ startCommand(cmd) {
186
+ this.currentAbort = new AbortController();
187
+ this.isExecuting = true;
188
+ this.executeCommand(cmd, this.currentAbort.signal)
189
+ .catch((err) => {
179
190
  this.log("[elys] unexpected error in executeCommand:", err);
191
+ })
192
+ .finally(() => {
193
+ this.isExecuting = false;
194
+ this.processPendingCommands();
180
195
  });
181
196
  }
197
+ processPendingCommands() {
198
+ if (this.pendingCommands.length === 0)
199
+ return;
200
+ // Merge all pending into one (debounce any that accumulated)
201
+ const pending = this.pendingCommands;
202
+ this.pendingCommands = [];
203
+ const merged = this.mergeCommands(pending);
204
+ this.log(`[elys] processing queued command ${merged.id}`);
205
+ this.startCommand(merged);
206
+ }
182
207
  /** Merge multiple buffered commands into one. Joins text args with newline. */
183
208
  mergeCommands(cmds) {
184
209
  if (cmds.length === 1)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-elys",
3
- "version": "1.7.4",
3
+ "version": "1.7.5",
4
4
  "description": "OpenClaw Elys channel plugin — connects to Elys App",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",