From 47c9560b9ea88535448c7b9493dac7982d575c39 Mon Sep 17 00:00:00 2001 From: paisley <8197966+su8su@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:46:33 +0800 Subject: [PATCH] Upgrade third party plugin (#715) --- electron/gateway/manager.ts | 26 +++++--- electron/gateway/restart-controller.ts | 22 +++++++ package.json | 12 ++-- pnpm-lock.yaml | 83 ++++++++++++-------------- 4 files changed, 84 insertions(+), 59 deletions(-) diff --git a/electron/gateway/manager.ts b/electron/gateway/manager.ts index 3b161f6d0..b118745af 100644 --- a/electron/gateway/manager.ts +++ b/electron/gateway/manager.ts @@ -427,6 +427,7 @@ export class GatewayManager extends EventEmitter { try { await this.restartInFlight; this.restartGovernor.recordExecuted(); + this.restartController.recordRestartCompleted(); const observability = this.restartGovernor.getObservability(); const props = { gateway_restart_executed_total: observability.executed_total, @@ -508,13 +509,6 @@ export class GatewayManager extends EventEmitter { return; } - if (process.platform === 'win32') { - logger.warn('[gateway-refresh] mode=reload result=fallback_restart cause=windows'); - logger.debug('Windows detected, falling back to Gateway restart for reload'); - await this.restart(); - return; - } - const connectedForMs = this.status.connectedAt ? Date.now() - this.status.connectedAt : Number.POSITIVE_INFINITY; @@ -528,6 +522,15 @@ export class GatewayManager extends EventEmitter { return; } + if (process.platform === 'win32') { + // Windows does not support SIGUSR1 for in-process reload. + // Fall back to a full restart. The connectedForMs < 8000 guard above + // already skips unnecessary restarts for recently-started processes. + logger.warn('[gateway-refresh] mode=reload result=fallback_restart cause=windows'); + await this.restart(); + return; + } + try { process.kill(this.process.pid, 'SIGUSR1'); logger.info(`Sent SIGUSR1 to Gateway for config reload (pid=${this.process.pid})`); @@ -785,7 +788,14 @@ export class GatewayManager extends EventEmitter { this.connectionMonitor.clear(); if (this.status.state === 'running') { this.setStatus({ state: 'stopped' }); - this.scheduleReconnect(); + // On Windows, skip reconnect from WS close. The Gateway is a local + // child process; actual crashes are already caught by the process exit + // handler (`onExit`) which calls scheduleReconnect(). Triggering + // reconnect from WS close as well races with the exit handler and can + // cause double start() attempts or port conflicts during TCP TIME_WAIT. + if (process.platform !== 'win32') { + this.scheduleReconnect(); + } } }, }); diff --git a/electron/gateway/restart-controller.ts b/electron/gateway/restart-controller.ts index 9db23df6f..73f1774da 100644 --- a/electron/gateway/restart-controller.ts +++ b/electron/gateway/restart-controller.ts @@ -16,6 +16,8 @@ type DeferredRestartContext = RestartDeferralState & { export class GatewayRestartController { private deferredRestartPending = false; + private deferredRestartRequestedAt = 0; + private lastRestartCompletedAt = 0; private restartDebounceTimer: NodeJS.Timeout | null = null; isRestartDeferred(context: RestartDeferralState): boolean { @@ -33,6 +35,13 @@ export class GatewayRestartController { ); } this.deferredRestartPending = true; + if (this.deferredRestartRequestedAt === 0) { + this.deferredRestartRequestedAt = Date.now(); + } + } + + recordRestartCompleted(): void { + this.lastRestartCompletedAt = Date.now(); } flushDeferredRestart( @@ -55,7 +64,9 @@ export class GatewayRestartController { return; } + const requestedAt = this.deferredRestartRequestedAt; this.deferredRestartPending = false; + this.deferredRestartRequestedAt = 0; if (action === 'drop') { logger.info( `Dropping deferred Gateway restart (${trigger}) because lifecycle already recovered (state=${context.state}, shouldReconnect=${context.shouldReconnect})`, @@ -63,6 +74,16 @@ export class GatewayRestartController { return; } + // If a restart already completed after this deferred request was made, + // the current process is already running with the latest config — + // skip the redundant restart to avoid "just started then restart" loops. + if (requestedAt > 0 && this.lastRestartCompletedAt >= requestedAt) { + logger.info( + `Dropping deferred Gateway restart (${trigger}): a restart already completed after the request (requested=${requestedAt}, completed=${this.lastRestartCompletedAt})`, + ); + return; + } + logger.info(`Executing deferred Gateway restart now (${trigger})`); executeRestart(); } @@ -87,5 +108,6 @@ export class GatewayRestartController { resetDeferredRestart(): void { this.deferredRestartPending = false; + this.deferredRestartRequestedAt = 0; } } diff --git a/package.json b/package.json index 97d322eeb..50abc1c1b 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ }, "devDependencies": { "@eslint/js": "^10.0.1", - "@larksuite/openclaw-lark": "2026.3.25", + "@larksuite/openclaw-lark": "2026.3.29", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.8", @@ -93,9 +93,9 @@ "@radix-ui/react-toast": "^1.2.15", "@radix-ui/react-tooltip": "^1.2.8", "@playwright/test": "^1.56.1", - "@soimy/dingtalk": "^3.4.2", - "@tencent-connect/openclaw-qqbot": "^1.6.5", - "@tencent-weixin/openclaw-weixin": "^2.0.1", + "@soimy/dingtalk": "^3.5.1", + "@tencent-connect/openclaw-qqbot": "^1.6.6", + "@tencent-weixin/openclaw-weixin": "^2.1.1", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@types/node": "^25.3.0", @@ -105,7 +105,7 @@ "@typescript-eslint/eslint-plugin": "^8.56.0", "@typescript-eslint/parser": "^8.56.0", "@vitejs/plugin-react": "^5.1.4", - "@wecom/wecom-openclaw-plugin": "^2026.3.24", + "@wecom/wecom-openclaw-plugin": "^2026.3.26", "@whiskeysockets/baileys": "7.0.0-rc.9", "autoprefixer": "^10.4.24", "class-variance-authority": "^0.7.1", @@ -144,4 +144,4 @@ "zx": "^8.8.5" }, "packageManager": "pnpm@10.31.0+sha512.e3927388bfaa8078ceb79b748ffc1e8274e84d75163e67bc22e06c0d3aed43dd153151cbf11d7f8301ff4acb98c68bdc5cadf6989532801ffafe3b3e4a63c268" -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd3ba60ea..41d2e0d73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,8 +44,8 @@ importers: specifier: ^10.0.1 version: 10.0.1(eslint@10.1.0(jiti@1.21.7)) '@larksuite/openclaw-lark': - specifier: 2026.3.25 - version: 2026.3.25(@napi-rs/canvas@0.1.97)(encoding@0.1.13) + specifier: 2026.3.29 + version: 2026.3.29(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13)) '@playwright/test': specifier: ^1.56.1 version: 1.58.2 @@ -86,14 +86,14 @@ importers: specifier: ^1.2.8 version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@soimy/dingtalk': - specifier: ^3.4.2 - version: 3.4.2(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13)) + specifier: ^3.5.1 + version: 3.5.1(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13)) '@tencent-connect/openclaw-qqbot': - specifier: ^1.6.5 - version: 1.6.5(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13)) + specifier: ^1.6.6 + version: 1.6.6(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13)) '@tencent-weixin/openclaw-weixin': - specifier: ^2.0.1 - version: 2.0.1(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13)) + specifier: ^2.1.1 + version: 2.1.1 '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -122,8 +122,8 @@ importers: specifier: ^5.1.4 version: 5.2.0(vite@7.3.1(@types/node@25.5.0)(jiti@1.21.7)(yaml@2.8.3)) '@wecom/wecom-openclaw-plugin': - specifier: ^2026.3.24 - version: 2026.3.25 + specifier: ^2026.3.26 + version: 2026.3.26 '@whiskeysockets/baileys': specifier: 7.0.0-rc.9 version: 7.0.0-rc.9(sharp@0.34.5) @@ -1076,12 +1076,15 @@ packages: '@keyv/serialize@1.1.1': resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} - '@larksuite/openclaw-lark@2026.3.25': - resolution: {integrity: sha512-SkNm0vuBLL58FFIVaDZ4vmdgTYXPfnfAy1vP2h+j0jnw5V+VSTj6IEKUq1oFmfyw7fIztUw/5GaM/quuMuRjog==} + '@larksuite/openclaw-lark@2026.3.29': + resolution: {integrity: sha512-dDUN7UWZBDVEfB7OGGwVBApE3uWgsVDiiJQV/MI0BrJODus3f4Eh65SU0PYLud5DbZ5uN7UcWFbn+5b3BQwOcw==} + engines: {node: '>=22'} hasBin: true + peerDependencies: + openclaw: '>=2026.3.22' - '@larksuiteoapi/node-sdk@1.59.0': - resolution: {integrity: sha512-sBpkruTvZDOxnVtoTbepWKRX0j1Y1ZElQYu0x7+v088sI9pcpbVp6ZzCGn62dhrKPatzNyCJyzYCPXPYQWccrA==} + '@larksuiteoapi/node-sdk@1.60.0': + resolution: {integrity: sha512-MS1eXx7K6HHIyIcCBkJLb21okoa8ZatUGQWZaCCUePm6a37RWFmT6ZKlKvHxAanSX26wNuNlwP0RhgscsE+T6g==} '@line/bot-sdk@10.6.0': resolution: {integrity: sha512-4hSpglL/G/cW2JCcohaYz/BS0uOSJNV9IEYdMm0EiPEvDLayoI2hGq2D86uYPQFD2gvgkyhmzdShpWLG3P5r3w==} @@ -2239,10 +2242,10 @@ packages: resolution: {integrity: sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==} engines: {node: '>=18.0.0'} - '@soimy/dingtalk@3.4.2': - resolution: {integrity: sha512-zUHxtRKp8Od3LG3o9sX9/xMOcqep24wZ836zhUwmFsJzS/dlkq356Ci1pn1Mvf8K1OdGSmFbmwCJTkTSLgRkfw==} + '@soimy/dingtalk@3.5.1': + resolution: {integrity: sha512-HRVkxy1v+Ee6qVEodnsdFJ7U3JeRqbcpSr1XjXAcxkWzsyUJoTdmEnmX4IqX4D4DDVOnx0IUh9kd9cDwCyeCVQ==} peerDependencies: - openclaw: '>=2026.3.14' + openclaw: '>=2026.3.24' '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -2254,8 +2257,8 @@ packages: '@telegraf/types@7.1.0': resolution: {integrity: sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==} - '@tencent-connect/openclaw-qqbot@1.6.5': - resolution: {integrity: sha512-791d8Jgq8VJMeK5NOmIqnXX+nZJpr49Eu5wBvtak9a2TBQukN3WQMqvwoHtZLwJkBocls664PHj/hNhVmBb7Mg==} + '@tencent-connect/openclaw-qqbot@1.6.6': + resolution: {integrity: sha512-Zn0oj0gGukvywRWB7/m2Bq82capwYsjUv+d+wAPZTBbJioR5A7J/z4U8o2YJOvw6e2vW67LkPmqTFf9qJkDDUg==} hasBin: true peerDependencies: openclaw: '*' @@ -2264,11 +2267,9 @@ packages: - silk-wasm - ws - '@tencent-weixin/openclaw-weixin@2.0.1': - resolution: {integrity: sha512-Ib7onvLU8a1ox9craMZxPwrN+ffJQJbToZzeMwoYryBOMIoBlVY0oCuQF7BZvZ7GRQQKOSSAdxvFkO47hKu0rg==} + '@tencent-weixin/openclaw-weixin@2.1.1': + resolution: {integrity: sha512-lSiTI+9eQQuvZXehuteNps3Ia4/ih5zml6QEgICwA2+9xT1sd5z8C+ldgRfrYd8lZTxYWC8ffkLtG0EVo2E7Ag==} engines: {node: '>=22'} - peerDependencies: - openclaw: '>=2026.3.22' '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} @@ -2507,8 +2508,8 @@ packages: '@wecom/aibot-node-sdk@1.0.4': resolution: {integrity: sha512-kZkrmlArq0NZyBvtOKw40m5nWTN1WlaA7XtqAo/1hn6N80P4c2mF99t3p1AMzj+dPo6OYvbsaelE8lbVWhkcBg==} - '@wecom/wecom-openclaw-plugin@2026.3.25': - resolution: {integrity: sha512-daPAaXVFrFlcQLB2g+7AEPrgKjIrVdC4WqhXMs7oSb1+qbvY+HYpvbDbX5VO0L8Mq1AnmOd4nS4Zobdfu3AMug==} + '@wecom/wecom-openclaw-plugin@2026.3.26': + resolution: {integrity: sha512-I7ZNO2UYQ0YyrRGhpqRKJgo7cCO3ONZtTO/C8sOUcg0KpELqEE2HVYP/7l5eWRB7v1HT0RI/SPnG3UTviGqAXA==} '@whiskeysockets/baileys@7.0.0-rc.9': resolution: {integrity: sha512-YFm5gKXfDP9byCXCW3OPHKXLzrAKzolzgVUlRosHHgwbnf2YOO3XknkMm6J7+F0ns8OA0uuSBhgkRHTDtqkacw==} @@ -2526,8 +2527,8 @@ packages: link-preview-js: optional: true - '@whiskeysockets/libsignal-node@git+https://github.com/whiskeysockets/libsignal-node.git#1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67': - resolution: {commit: 1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67, repo: https://github.com/whiskeysockets/libsignal-node.git, type: git} + '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67': + resolution: {tarball: https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67} version: 2.0.1 '@xmldom/xmldom@0.8.11': @@ -7075,26 +7076,19 @@ snapshots: '@keyv/serialize@1.1.1': {} - '@larksuite/openclaw-lark@2026.3.25(@napi-rs/canvas@0.1.97)(encoding@0.1.13)': + '@larksuite/openclaw-lark@2026.3.29(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13))': dependencies: - '@larksuiteoapi/node-sdk': 1.59.0 + '@larksuiteoapi/node-sdk': 1.60.0 '@sinclair/typebox': 0.34.48 image-size: 2.0.2 openclaw: 2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13) zod: 4.3.6 transitivePeerDependencies: - - '@cfworker/json-schema' - - '@napi-rs/canvas' - - aws-crt - bufferutil - - canvas - debug - - encoding - - node-llama-cpp - - supports-color - utf-8-validate - '@larksuiteoapi/node-sdk@1.59.0': + '@larksuiteoapi/node-sdk@1.60.0': dependencies: axios: 1.13.6(debug@4.4.3) lodash.identity: 3.0.0 @@ -8303,7 +8297,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@soimy/dingtalk@3.4.2(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13))': + '@soimy/dingtalk@3.5.1(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13))': dependencies: axios: 1.13.6(debug@4.4.3) dingtalk-stream: 2.1.5 @@ -8327,13 +8321,12 @@ snapshots: '@telegraf/types@7.1.0': optional: true - '@tencent-connect/openclaw-qqbot@1.6.5(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13))': + '@tencent-connect/openclaw-qqbot@1.6.6(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13))': dependencies: openclaw: 2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13) - '@tencent-weixin/openclaw-weixin@2.0.1(openclaw@2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13))': + '@tencent-weixin/openclaw-weixin@2.1.1': dependencies: - openclaw: 2026.3.24(@napi-rs/canvas@0.1.97)(encoding@0.1.13) qrcode-terminal: 0.12.0 zod: 4.3.6 @@ -8655,7 +8648,7 @@ snapshots: - debug - utf-8-validate - '@wecom/wecom-openclaw-plugin@2026.3.25': + '@wecom/wecom-openclaw-plugin@2026.3.26': dependencies: '@wecom/aibot-node-sdk': 1.0.4 file-type: 21.3.4 @@ -8670,7 +8663,7 @@ snapshots: '@cacheable/node-cache': 1.7.6 '@hapi/boom': 9.1.4 async-mutex: 0.5.0 - libsignal: '@whiskeysockets/libsignal-node@git+https://github.com/whiskeysockets/libsignal-node.git#1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67' + libsignal: '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67' lru-cache: 11.2.7 music-metadata: 11.12.3 p-queue: 9.1.0 @@ -8683,7 +8676,7 @@ snapshots: - supports-color - utf-8-validate - '@whiskeysockets/libsignal-node@git+https://github.com/whiskeysockets/libsignal-node.git#1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67': + '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67': dependencies: curve25519-js: 0.0.4 protobufjs: 6.8.8 @@ -11394,7 +11387,7 @@ snapshots: pdfjs-dist@5.4.296: optionalDependencies: - '@napi-rs/canvas': 0.1.80 + '@napi-rs/canvas': 0.1.97 pdfjs-dist@5.5.207: optionalDependencies: