feat(electron): auto-upgrade bundled OpenClaw plugins at app startup (#521)

This commit is contained in:
paisley
2026-03-16 13:19:06 +08:00
committed by GitHub
Unverified
parent 02d38d15db
commit 9ec23174c0
6 changed files with 172 additions and 292 deletions

View File

@@ -1,8 +1,4 @@
import type { IncomingMessage, ServerResponse } from 'http'; import type { IncomingMessage, ServerResponse } from 'http';
import { app } from 'electron';
import { existsSync, cpSync, mkdirSync, rmSync, readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { import {
deleteChannelConfig, deleteChannelConfig,
getChannelFormValues, getChannelFormValues,
@@ -12,6 +8,12 @@ import {
validateChannelConfig, validateChannelConfig,
validateChannelCredentials, validateChannelCredentials,
} from '../../utils/channel-config'; } from '../../utils/channel-config';
import {
ensureDingTalkPluginInstalled,
ensureFeishuPluginInstalled,
ensureQQBotPluginInstalled,
ensureWeComPluginInstalled,
} from '../../utils/plugin-install';
import { assignChannelToAgent, clearAllBindingsForChannel } from '../../utils/agent-config'; import { assignChannelToAgent, clearAllBindingsForChannel } from '../../utils/agent-config';
import { whatsAppLoginManager } from '../../utils/whatsapp-login'; import { whatsAppLoginManager } from '../../utils/whatsapp-login';
import type { HostApiContext } from '../context'; import type { HostApiContext } from '../context';
@@ -46,100 +48,6 @@ function scheduleGatewayChannelSaveRefresh(
void reason; void reason;
} }
// ── Generic plugin installer with version-aware upgrades ─────────
function readPluginVersion(pkgJsonPath: string): string | null {
try {
const raw = readFileSync(pkgJsonPath, 'utf-8');
const parsed = JSON.parse(raw) as { version?: string };
return parsed.version ?? null;
} catch {
return null;
}
}
function ensurePluginInstalled(
pluginDirName: string,
candidateSources: string[],
pluginLabel: string,
): { installed: boolean; warning?: string } {
const targetDir = join(homedir(), '.openclaw', 'extensions', pluginDirName);
const targetManifest = join(targetDir, 'openclaw.plugin.json');
const targetPkgJson = join(targetDir, 'package.json');
const sourceDir = candidateSources.find((dir) => existsSync(join(dir, 'openclaw.plugin.json')));
// If already installed, check whether an upgrade is available
if (existsSync(targetManifest)) {
if (!sourceDir) return { installed: true }; // no bundled source to compare, keep existing
const installedVersion = readPluginVersion(targetPkgJson);
const sourceVersion = readPluginVersion(join(sourceDir, 'package.json'));
if (!sourceVersion || !installedVersion || sourceVersion === installedVersion) {
return { installed: true }; // same version or unable to compare
}
// Version differs — fall through to overwrite install
console.log(
`[plugin] Upgrading ${pluginLabel} plugin: ${installedVersion}${sourceVersion}`,
);
}
// Fresh install or upgrade
if (!sourceDir) {
return {
installed: false,
warning: `Bundled ${pluginLabel} plugin mirror not found. Checked: ${candidateSources.join(' | ')}`,
};
}
try {
mkdirSync(join(homedir(), '.openclaw', 'extensions'), { recursive: true });
rmSync(targetDir, { recursive: true, force: true });
cpSync(sourceDir, targetDir, { recursive: true, dereference: true });
if (!existsSync(join(targetDir, 'openclaw.plugin.json'))) {
return { installed: false, warning: `Failed to install ${pluginLabel} plugin mirror (manifest missing).` };
}
return { installed: true };
} catch {
return { installed: false, warning: `Failed to install bundled ${pluginLabel} plugin mirror` };
}
}
// ── Per-channel plugin helpers (thin wrappers around ensurePluginInstalled) ──
function buildCandidateSources(pluginDirName: string): string[] {
return app.isPackaged
? [
join(process.resourcesPath, 'openclaw-plugins', pluginDirName),
join(process.resourcesPath, 'app.asar.unpacked', 'build', 'openclaw-plugins', pluginDirName),
join(process.resourcesPath, 'app.asar.unpacked', 'openclaw-plugins', pluginDirName),
]
: [
join(app.getAppPath(), 'build', 'openclaw-plugins', pluginDirName),
join(process.cwd(), 'build', 'openclaw-plugins', pluginDirName),
join(__dirname, '../../../build/openclaw-plugins', pluginDirName),
];
}
function ensureDingTalkPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('dingtalk', buildCandidateSources('dingtalk'), 'DingTalk');
}
function ensureWeComPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('wecom', buildCandidateSources('wecom'), 'WeCom');
}
function ensureFeishuPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled(
'feishu-openclaw-plugin',
buildCandidateSources('feishu-openclaw-plugin'),
'Feishu',
);
}
function ensureQQBotPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('qqbot', buildCandidateSources('qqbot'), 'QQ Bot');
}
function toComparableConfig(input: Record<string, unknown>): Record<string, string> { function toComparableConfig(input: Record<string, unknown>): Record<string, string> {
const next: Record<string, string> = {}; const next: Record<string, string> = {};
for (const [key, value] of Object.entries(input)) { for (const [key, value] of Object.entries(input)) {

View File

@@ -29,6 +29,7 @@ import {
} from './main-window-focus'; } from './main-window-focus';
import { getSetting } from '../utils/store'; import { getSetting } from '../utils/store';
import { ensureBuiltinSkillsInstalled, ensurePreinstalledSkillsInstalled } from '../utils/skill-config'; import { ensureBuiltinSkillsInstalled, ensurePreinstalledSkillsInstalled } from '../utils/skill-config';
import { ensureAllBundledPluginsInstalled } from '../utils/plugin-install';
import { startHostApiServer } from '../api/server'; import { startHostApiServer } from '../api/server';
import { HostEventBus } from '../api/event-bus'; import { HostEventBus } from '../api/event-bus';
import { deviceOAuthManager } from '../utils/device-oauth'; import { deviceOAuthManager } from '../utils/device-oauth';
@@ -294,6 +295,12 @@ async function initialize(): Promise<void> {
logger.warn('Failed to install preinstalled skills:', error); logger.warn('Failed to install preinstalled skills:', error);
}); });
// Pre-deploy/upgrade bundled OpenClaw plugins (dingtalk, wecom, qqbot, feishu)
// to ~/.openclaw/extensions/ so they are always up-to-date after an app update.
void ensureAllBundledPluginsInstalled().catch((error) => {
logger.warn('Failed to install/upgrade bundled plugins:', error);
});
// Bridge gateway and host-side events before any auto-start logic runs, so // Bridge gateway and host-side events before any auto-start logic runs, so
// renderer subscribers observe the full startup lifecycle. // renderer subscribers observe the full startup lifecycle.
gatewayManager.on('status', (status: { state: string }) => { gatewayManager.on('status', (status: { state: string }) => {

View File

@@ -3,7 +3,7 @@
* Registers all IPC handlers for main-renderer communication * Registers all IPC handlers for main-renderer communication
*/ */
import { ipcMain, BrowserWindow, shell, dialog, app, nativeImage } from 'electron'; import { ipcMain, BrowserWindow, shell, dialog, app, nativeImage } from 'electron';
import { existsSync, cpSync, mkdirSync, rmSync, readFileSync } from 'node:fs'; import { existsSync } from 'node:fs';
import { homedir } from 'node:os'; import { homedir } from 'node:os';
import { join, extname, basename } from 'node:path'; import { join, extname, basename } from 'node:path';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
@@ -32,6 +32,12 @@ import {
validateChannelCredentials, validateChannelCredentials,
} from '../utils/channel-config'; } from '../utils/channel-config';
import { checkUvInstalled, installUv, setupManagedPython } from '../utils/uv-setup'; import { checkUvInstalled, installUv, setupManagedPython } from '../utils/uv-setup';
import {
ensureDingTalkPluginInstalled,
ensureFeishuPluginInstalled,
ensureQQBotPluginInstalled,
ensureWeComPluginInstalled,
} from '../utils/plugin-install';
import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/skill-config'; import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/skill-config';
import { whatsAppLoginManager } from '../utils/whatsapp-login'; import { whatsAppLoginManager } from '../utils/whatsapp-login';
import { getProviderConfig } from '../utils/provider-registry'; import { getProviderConfig } from '../utils/provider-registry';
@@ -1382,102 +1388,6 @@ function registerOpenClawHandlers(gatewayManager: GatewayManager): void {
gatewayManager.debouncedReload(); gatewayManager.debouncedReload();
}; };
// ── Generic plugin installer with version-aware upgrades ─────────
function readPluginVersion(pkgJsonPath: string): string | null {
try {
const raw = readFileSync(pkgJsonPath, 'utf-8');
const parsed = JSON.parse(raw) as { version?: string };
return parsed.version ?? null;
} catch {
return null;
}
}
function ensurePluginInstalled(
pluginDirName: string,
candidateSources: string[],
pluginLabel: string,
): { installed: boolean; warning?: string } {
const targetDir = join(homedir(), '.openclaw', 'extensions', pluginDirName);
const targetManifest = join(targetDir, 'openclaw.plugin.json');
const targetPkgJson = join(targetDir, 'package.json');
const sourceDir = candidateSources.find((dir) => existsSync(join(dir, 'openclaw.plugin.json')));
// If already installed, check whether an upgrade is available
if (existsSync(targetManifest)) {
if (!sourceDir) return { installed: true };
const installedVersion = readPluginVersion(targetPkgJson);
const sourceVersion = readPluginVersion(join(sourceDir, 'package.json'));
if (!sourceVersion || !installedVersion || sourceVersion === installedVersion) {
return { installed: true };
}
logger.info(`[plugin] Upgrading ${pluginLabel} plugin: ${installedVersion}${sourceVersion}`);
}
if (!sourceDir) {
logger.warn(`Bundled ${pluginLabel} plugin mirror not found in candidate paths`, { candidateSources });
return {
installed: false,
warning: `Bundled ${pluginLabel} plugin mirror not found. Checked: ${candidateSources.join(' | ')}`,
};
}
try {
mkdirSync(join(homedir(), '.openclaw', 'extensions'), { recursive: true });
rmSync(targetDir, { recursive: true, force: true });
cpSync(sourceDir, targetDir, { recursive: true, dereference: true });
if (!existsSync(join(targetDir, 'openclaw.plugin.json'))) {
return { installed: false, warning: `Failed to install ${pluginLabel} plugin mirror (manifest missing).` };
}
logger.info(`Installed ${pluginLabel} plugin from bundled mirror: ${sourceDir}`);
return { installed: true };
} catch (error) {
logger.warn(`Failed to install ${pluginLabel} plugin from bundled mirror:`, error);
return {
installed: false,
warning: `Failed to install bundled ${pluginLabel} plugin mirror`,
};
}
}
function buildCandidateSources(pluginDirName: string): string[] {
return app.isPackaged
? [
join(process.resourcesPath, 'openclaw-plugins', pluginDirName),
join(process.resourcesPath, 'app.asar.unpacked', 'build', 'openclaw-plugins', pluginDirName),
join(process.resourcesPath, 'app.asar.unpacked', 'openclaw-plugins', pluginDirName),
]
: [
join(app.getAppPath(), 'build', 'openclaw-plugins', pluginDirName),
join(process.cwd(), 'build', 'openclaw-plugins', pluginDirName),
join(__dirname, '../../build/openclaw-plugins', pluginDirName),
];
}
function ensureDingTalkPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('dingtalk', buildCandidateSources('dingtalk'), 'DingTalk');
}
function ensureWeComPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('wecom', buildCandidateSources('wecom'), 'WeCom');
}
function ensureFeishuPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled(
'feishu-openclaw-plugin',
buildCandidateSources('feishu-openclaw-plugin'),
'Feishu',
);
}
function ensureQQBotPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('qqbot', buildCandidateSources('qqbot'), 'QQ Bot');
}
// Get OpenClaw package status // Get OpenClaw package status
ipcMain.handle('openclaw:status', () => { ipcMain.handle('openclaw:status', () => {
const status = getOpenClawStatus(); const status = getOpenClawStatus();

View File

@@ -0,0 +1,141 @@
/**
* Shared OpenClaw Plugin Install Utilities
*
* Provides version-aware install/upgrade logic for bundled OpenClaw plugins
* (DingTalk, WeCom, QQBot, Feishu). Used both at app startup (to auto-upgrade
* stale plugins) and when a user configures a channel.
*/
import { app } from 'electron';
import { existsSync, cpSync, mkdirSync, rmSync, readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { logger } from './logger';
// ── Version helper ───────────────────────────────────────────────────────────
function readPluginVersion(pkgJsonPath: string): string | null {
try {
const raw = readFileSync(pkgJsonPath, 'utf-8');
const parsed = JSON.parse(raw) as { version?: string };
return parsed.version ?? null;
} catch {
return null;
}
}
// ── Core install / upgrade logic ─────────────────────────────────────────────
export function ensurePluginInstalled(
pluginDirName: string,
candidateSources: string[],
pluginLabel: string,
): { installed: boolean; warning?: string } {
const targetDir = join(homedir(), '.openclaw', 'extensions', pluginDirName);
const targetManifest = join(targetDir, 'openclaw.plugin.json');
const targetPkgJson = join(targetDir, 'package.json');
const sourceDir = candidateSources.find((dir) => existsSync(join(dir, 'openclaw.plugin.json')));
// If already installed, check whether an upgrade is available
if (existsSync(targetManifest)) {
if (!sourceDir) return { installed: true }; // no bundled source to compare, keep existing
const installedVersion = readPluginVersion(targetPkgJson);
const sourceVersion = readPluginVersion(join(sourceDir, 'package.json'));
if (!sourceVersion || !installedVersion || sourceVersion === installedVersion) {
return { installed: true }; // same version or unable to compare
}
// Version differs — fall through to overwrite install
logger.info(
`[plugin] Upgrading ${pluginLabel} plugin: ${installedVersion}${sourceVersion}`,
);
}
// Fresh install or upgrade
if (!sourceDir) {
return {
installed: false,
warning: `Bundled ${pluginLabel} plugin mirror not found. Checked: ${candidateSources.join(' | ')}`,
};
}
try {
mkdirSync(join(homedir(), '.openclaw', 'extensions'), { recursive: true });
rmSync(targetDir, { recursive: true, force: true });
cpSync(sourceDir, targetDir, { recursive: true, dereference: true });
if (!existsSync(join(targetDir, 'openclaw.plugin.json'))) {
return { installed: false, warning: `Failed to install ${pluginLabel} plugin mirror (manifest missing).` };
}
logger.info(`Installed ${pluginLabel} plugin from bundled mirror: ${sourceDir}`);
return { installed: true };
} catch {
return { installed: false, warning: `Failed to install bundled ${pluginLabel} plugin mirror` };
}
}
// ── Candidate source path builder ────────────────────────────────────────────
export function buildCandidateSources(pluginDirName: string): string[] {
return app.isPackaged
? [
join(process.resourcesPath, 'openclaw-plugins', pluginDirName),
join(process.resourcesPath, 'app.asar.unpacked', 'build', 'openclaw-plugins', pluginDirName),
join(process.resourcesPath, 'app.asar.unpacked', 'openclaw-plugins', pluginDirName),
]
: [
join(app.getAppPath(), 'build', 'openclaw-plugins', pluginDirName),
join(process.cwd(), 'build', 'openclaw-plugins', pluginDirName),
join(__dirname, '../../build/openclaw-plugins', pluginDirName),
];
}
// ── Per-channel plugin helpers ───────────────────────────────────────────────
export function ensureDingTalkPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('dingtalk', buildCandidateSources('dingtalk'), 'DingTalk');
}
export function ensureWeComPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('wecom', buildCandidateSources('wecom'), 'WeCom');
}
export function ensureFeishuPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled(
'feishu-openclaw-plugin',
buildCandidateSources('feishu-openclaw-plugin'),
'Feishu',
);
}
export function ensureQQBotPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('qqbot', buildCandidateSources('qqbot'), 'QQ Bot');
}
// ── Bulk startup installer ───────────────────────────────────────────────────
/**
* All bundled plugins, in the same order as after-pack.cjs BUNDLED_PLUGINS.
*/
const ALL_BUNDLED_PLUGINS = [
{ fn: ensureDingTalkPluginInstalled, label: 'DingTalk' },
{ fn: ensureWeComPluginInstalled, label: 'WeCom' },
{ fn: ensureQQBotPluginInstalled, label: 'QQ Bot' },
{ fn: ensureFeishuPluginInstalled, label: 'Feishu' },
] as const;
/**
* Ensure all bundled OpenClaw plugins are installed/upgraded in
* `~/.openclaw/extensions/`. Designed to be called once at app startup
* as a fire-and-forget task — errors are logged but never thrown.
*/
export async function ensureAllBundledPluginsInstalled(): Promise<void> {
for (const { fn, label } of ALL_BUNDLED_PLUGINS) {
try {
const result = fn();
if (result.warning) {
logger.warn(`[plugin] ${label}: ${result.warning}`);
}
} catch (error) {
logger.warn(`[plugin] Failed to install/upgrade ${label} plugin:`, error);
}
}
}

View File

@@ -61,7 +61,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
"@larksuite/openclaw-lark": "2026.3.12", "@larksuite/openclaw-lark": "2026.3.15",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.8", "@radix-ui/react-label": "^2.1.8",

106
pnpm-lock.yaml generated
View File

@@ -37,8 +37,8 @@ importers:
specifier: ^10.0.1 specifier: ^10.0.1
version: 10.0.1(eslint@10.0.0(jiti@1.21.7)) version: 10.0.1(eslint@10.0.0(jiti@1.21.7))
'@larksuite/openclaw-lark': '@larksuite/openclaw-lark':
specifier: 2026.3.12 specifier: 2026.3.15
version: 2026.3.12 version: 2026.3.15
'@radix-ui/react-dialog': '@radix-ui/react-dialog':
specifier: ^1.1.15 specifier: ^1.1.15
version: 1.1.15(@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) version: 1.1.15(@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)
@@ -296,10 +296,6 @@ packages:
resolution: {integrity: sha512-ag7Qx78m1K3Dv7xlFgeHS4jBdopGZUISgVBMUy7Cj4fIgVH9EBmsc5K4hWozL8BJQctWke8Wsl96O7Gd+HCGhg==} resolution: {integrity: sha512-ag7Qx78m1K3Dv7xlFgeHS4jBdopGZUISgVBMUy7Cj4fIgVH9EBmsc5K4hWozL8BJQctWke8Wsl96O7Gd+HCGhg==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
'@aws-sdk/client-bedrock@3.1006.0':
resolution: {integrity: sha512-CWUrrlWaFDYZIK2rNIa9FUVn3wC3lZszz0r6bq5yRiRj1P+dSd+ZpGdlRYDAi6Nq9dsainEXdpadiuUwzL6YZQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/client-bedrock@3.1009.0': '@aws-sdk/client-bedrock@3.1009.0':
resolution: {integrity: sha512-KzLNqSg1T59sSlQvEA4EL3oDIAMidM54AB1b+UGouPFuUrrwGp2uUlZUYzIIlCvqpf7wEDh8wypqXISRItkgdg==} resolution: {integrity: sha512-KzLNqSg1T59sSlQvEA4EL3oDIAMidM54AB1b+UGouPFuUrrwGp2uUlZUYzIIlCvqpf7wEDh8wypqXISRItkgdg==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
@@ -444,10 +440,6 @@ packages:
resolution: {integrity: sha512-vMxd+ivKqSxU9bHx5vmAlFKDAkjGotFU56IOkDa5DaTu1WWwbcse0yFHEm9I537oVvodaiwMl3VBwgHfzQ2rvw==} resolution: {integrity: sha512-vMxd+ivKqSxU9bHx5vmAlFKDAkjGotFU56IOkDa5DaTu1WWwbcse0yFHEm9I537oVvodaiwMl3VBwgHfzQ2rvw==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
'@aws-sdk/token-providers@3.1006.0':
resolution: {integrity: sha512-eCBaQI1w5PcliOdh8Y0YONOim2zNSTEK4E7gXYC4vIqiT/lzVODIFxmpc8oOBLPSANzcr9daIPPtjQ2C75dLFg==}
engines: {node: '>=20.0.0'}
'@aws-sdk/token-providers@3.1009.0': '@aws-sdk/token-providers@3.1009.0':
resolution: {integrity: sha512-KCPLuTqN9u0Rr38Arln78fRG9KXpzsPWmof+PZzfAHMMQq2QED6YjQrkrfiH7PDefLWEposY1o4/eGwrmKA4JA==} resolution: {integrity: sha512-KCPLuTqN9u0Rr38Arln78fRG9KXpzsPWmof+PZzfAHMMQq2QED6YjQrkrfiH7PDefLWEposY1o4/eGwrmKA4JA==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
@@ -1229,8 +1221,8 @@ packages:
'@kwsites/promise-deferred@1.1.1': '@kwsites/promise-deferred@1.1.1':
resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==}
'@larksuite/openclaw-lark@2026.3.12': '@larksuite/openclaw-lark@2026.3.15':
resolution: {integrity: sha512-MNcDrerQrO42I09w+M8q6dwnWHMKxOnXSCLG4qNwcekjGeDmA53lIuWJtGMpjTzvDjYkoWnN+8Zg78+FRCSV9w==} resolution: {integrity: sha512-YGk63CgYG+YDUO2+TxdSPJZA6km52OpqAqf26vZHMUqawEKhiT4bcfD5JHh6VGazjUwRk5Bze1UyVKncc0csBA==}
'@larksuiteoapi/node-sdk@1.59.0': '@larksuiteoapi/node-sdk@1.59.0':
resolution: {integrity: sha512-sBpkruTvZDOxnVtoTbepWKRX0j1Y1ZElQYu0x7+v088sI9pcpbVp6ZzCGn62dhrKPatzNyCJyzYCPXPYQWccrA==} resolution: {integrity: sha512-sBpkruTvZDOxnVtoTbepWKRX0j1Y1ZElQYu0x7+v088sI9pcpbVp6ZzCGn62dhrKPatzNyCJyzYCPXPYQWccrA==}
@@ -2513,10 +2505,6 @@ packages:
resolution: {integrity: sha512-eWX2mdt1ktpn8+40iiMc404uGrih+2fxiky3zBcPjtXKj6HLRdYlmhrPkJi7JTJm8dpXR6BWVWEDBXtaWMKD6A==} resolution: {integrity: sha512-eWX2mdt1ktpn8+40iiMc404uGrih+2fxiky3zBcPjtXKj6HLRdYlmhrPkJi7JTJm8dpXR6BWVWEDBXtaWMKD6A==}
engines: {node: '>= 12.13.0', npm: '>= 6.12.0'} engines: {node: '>= 12.13.0', npm: '>= 6.12.0'}
'@slack/web-api@7.14.1':
resolution: {integrity: sha512-RoygyteJeFswxDPJjUMESn9dldWVMD2xUcHHd9DenVavSfVC6FeVnSdDerOO7m8LLvw4Q132nQM4hX8JiF7dng==}
engines: {node: '>= 18', npm: '>= 8.6.0'}
'@slack/web-api@7.15.0': '@slack/web-api@7.15.0':
resolution: {integrity: sha512-va7zYIt3QHG1x9M/jqXXRPFMoOVlVSSRHC5YH+DzKYsrz5xUKOA3lR4THsu/Zxha9N1jOndbKFKLtr0WOPW1Vw==} resolution: {integrity: sha512-va7zYIt3QHG1x9M/jqXXRPFMoOVlVSSRHC5YH+DzKYsrz5xUKOA3lR4THsu/Zxha9N1jOndbKFKLtr0WOPW1Vw==}
engines: {node: '>= 18', npm: '>= 8.6.0'} engines: {node: '>= 18', npm: '>= 8.6.0'}
@@ -7211,51 +7199,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- aws-crt - aws-crt
'@aws-sdk/client-bedrock@3.1006.0':
dependencies:
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.973.19
'@aws-sdk/credential-provider-node': 3.972.19
'@aws-sdk/middleware-host-header': 3.972.7
'@aws-sdk/middleware-logger': 3.972.7
'@aws-sdk/middleware-recursion-detection': 3.972.7
'@aws-sdk/middleware-user-agent': 3.972.20
'@aws-sdk/region-config-resolver': 3.972.7
'@aws-sdk/token-providers': 3.1006.0
'@aws-sdk/types': 3.973.5
'@aws-sdk/util-endpoints': 3.996.4
'@aws-sdk/util-user-agent-browser': 3.972.7
'@aws-sdk/util-user-agent-node': 3.973.5
'@smithy/config-resolver': 4.4.10
'@smithy/core': 3.23.9
'@smithy/fetch-http-handler': 5.3.13
'@smithy/hash-node': 4.2.11
'@smithy/invalid-dependency': 4.2.11
'@smithy/middleware-content-length': 4.2.11
'@smithy/middleware-endpoint': 4.4.23
'@smithy/middleware-retry': 4.4.40
'@smithy/middleware-serde': 4.2.12
'@smithy/middleware-stack': 4.2.11
'@smithy/node-config-provider': 4.3.11
'@smithy/node-http-handler': 4.4.14
'@smithy/protocol-http': 5.3.11
'@smithy/smithy-client': 4.12.3
'@smithy/types': 4.13.0
'@smithy/url-parser': 4.2.11
'@smithy/util-base64': 4.3.2
'@smithy/util-body-length-browser': 4.2.2
'@smithy/util-body-length-node': 4.2.3
'@smithy/util-defaults-mode-browser': 4.3.39
'@smithy/util-defaults-mode-node': 4.2.42
'@smithy/util-endpoints': 3.3.2
'@smithy/util-middleware': 4.2.11
'@smithy/util-retry': 4.2.11
'@smithy/util-utf8': 4.2.2
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/client-bedrock@3.1009.0': '@aws-sdk/client-bedrock@3.1009.0':
dependencies: dependencies:
'@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0
@@ -7791,18 +7734,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- aws-crt - aws-crt
'@aws-sdk/token-providers@3.1006.0':
dependencies:
'@aws-sdk/core': 3.973.19
'@aws-sdk/nested-clients': 3.996.8
'@aws-sdk/types': 3.973.5
'@smithy/property-provider': 4.2.11
'@smithy/shared-ini-file-loader': 4.4.6
'@smithy/types': 4.13.0
tslib: 2.8.1
transitivePeerDependencies:
- aws-crt
'@aws-sdk/token-providers@3.1009.0': '@aws-sdk/token-providers@3.1009.0':
dependencies: dependencies:
'@aws-sdk/core': 3.973.20 '@aws-sdk/core': 3.973.20
@@ -8671,7 +8602,7 @@ snapshots:
'@kwsites/promise-deferred@1.1.1': '@kwsites/promise-deferred@1.1.1':
optional: true optional: true
'@larksuite/openclaw-lark@2026.3.12': '@larksuite/openclaw-lark@2026.3.15':
dependencies: dependencies:
'@larksuiteoapi/node-sdk': 1.59.0 '@larksuiteoapi/node-sdk': 1.59.0
'@sinclair/typebox': 0.34.48 '@sinclair/typebox': 0.34.48
@@ -8874,7 +8805,7 @@ snapshots:
chalk: 5.6.2 chalk: 5.6.2
cli-highlight: 2.1.11 cli-highlight: 2.1.11
diff: 8.0.3 diff: 8.0.3
file-type: 21.3.0 file-type: 21.3.2
glob: 11.1.0 glob: 11.1.0
marked: 15.0.12 marked: 15.0.12
minimatch: 10.2.4 minimatch: 10.2.4
@@ -9961,23 +9892,6 @@ snapshots:
'@slack/types@2.20.1': {} '@slack/types@2.20.1': {}
'@slack/web-api@7.14.1':
dependencies:
'@slack/logger': 4.0.0
'@slack/types': 2.20.0
'@types/node': 25.3.0
'@types/retry': 0.12.0
axios: 1.13.5(debug@4.4.3)
eventemitter3: 5.0.4
form-data: 4.0.5
is-electron: 2.2.2
is-stream: 2.0.1
p-queue: 6.6.2
p-retry: 4.6.2
retry: 0.13.1
transitivePeerDependencies:
- debug
'@slack/web-api@7.15.0': '@slack/web-api@7.15.0':
dependencies: dependencies:
'@slack/logger': 4.0.1 '@slack/logger': 4.0.1
@@ -11467,7 +11381,7 @@ snapshots:
clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@modelcontextprotocol/sdk@1.27.1(zod@4.3.6))(@types/express@5.0.6)(devtools-protocol@0.0.1596832)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3): clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@modelcontextprotocol/sdk@1.27.1(zod@4.3.6))(@types/express@5.0.6)(devtools-protocol@0.0.1596832)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3):
dependencies: dependencies:
'@agentclientprotocol/sdk': 0.13.1(zod@4.3.6) '@agentclientprotocol/sdk': 0.13.1(zod@4.3.6)
'@aws-sdk/client-bedrock': 3.1006.0 '@aws-sdk/client-bedrock': 3.1009.0
'@buape/carbon': 0.14.0(@discordjs/opus@0.10.0(encoding@0.1.13))(hono@4.11.4)(opusscript@0.1.1) '@buape/carbon': 0.14.0(@discordjs/opus@0.10.0(encoding@0.1.13))(hono@4.11.4)(opusscript@0.1.1)
'@clack/prompts': 0.11.0 '@clack/prompts': 0.11.0
'@grammyjs/runner': 2.0.3(grammy@1.41.1(encoding@0.1.13)) '@grammyjs/runner': 2.0.3(grammy@1.41.1(encoding@0.1.13))
@@ -11482,7 +11396,7 @@ snapshots:
'@mozilla/readability': 0.6.0 '@mozilla/readability': 0.6.0
'@sinclair/typebox': 0.34.47 '@sinclair/typebox': 0.34.47
'@slack/bolt': 4.6.0(@types/express@5.0.6) '@slack/bolt': 4.6.0(@types/express@5.0.6)
'@slack/web-api': 7.14.1 '@slack/web-api': 7.15.0
'@whiskeysockets/baileys': 7.0.0-rc.9(sharp@0.34.5) '@whiskeysockets/baileys': 7.0.0-rc.9(sharp@0.34.5)
ajv: 8.18.0 ajv: 8.18.0
body-parser: 2.2.2 body-parser: 2.2.2
@@ -11496,7 +11410,7 @@ snapshots:
discord-api-types: 0.38.42 discord-api-types: 0.38.42
dotenv: 17.3.1 dotenv: 17.3.1
express: 5.2.1 express: 5.2.1
file-type: 21.3.0 file-type: 21.3.2
grammy: 1.41.1(encoding@0.1.13) grammy: 1.41.1(encoding@0.1.13)
hono: 4.11.4 hono: 4.11.4
jiti: 2.6.1 jiti: 2.6.1
@@ -11515,7 +11429,7 @@ snapshots:
sqlite-vec: 0.1.7-alpha.2 sqlite-vec: 0.1.7-alpha.2
tar: 7.5.4 tar: 7.5.4
tslog: 4.10.2 tslog: 4.10.2
undici: 7.22.0 undici: 7.24.1
ws: 8.19.0 ws: 8.19.0
yaml: 2.8.2 yaml: 2.8.2
zod: 4.3.6 zod: 4.3.6