From ba754ccc31ec86e66a758ea062ea06bb1561069c Mon Sep 17 00:00:00 2001 From: HenryXiaoYang Date: Tue, 10 Mar 2026 02:29:06 +0800 Subject: [PATCH] feat: add WeChat QR code login and AGP WebSocket channel plugin - Auth module: WeChat OAuth2 scan-to-login flow with terminal QR code - Token persistence to ~/.openclaw/wechat-access-auth.json (chmod 600) - Token resolution: config > saved state > interactive login - Invite code verification (configurable bypass) - Production/test environment support - AGP WebSocket client with heartbeat, reconnect, wake detection - Message handler: Agent dispatch with streaming text and tool calls - Random device GUID generation (persisted, no real machine ID) --- .gitignore | 21 + README.md | 81 + auth/device-guid.ts | 43 + auth/environments.ts | 29 + auth/index.ts | 19 + auth/qclaw-api.ts | 129 + auth/state-store.ts | 48 + auth/types.ts | 57 + auth/utils.ts | 14 + auth/wechat-login.ts | 238 + common/agent-events.ts | 49 + common/message-context.ts | 174 + common/runtime.ts | 35 + http/README.md | 138 + http/callback-service.ts | 73 + http/crypto-utils.ts | 96 + http/http-utils.ts | 81 + http/index.ts | 59 + http/message-context.ts | 4 + http/message-handler.ts | 560 ++ http/types.ts | 148 + http/webhook.ts | 278 + index.ts | 236 + openclaw.plugin.json | 38 + package-lock.json | 10202 ++++++++++++++++++++++++++++++++ package.json | 44 + tsconfig.json | 28 + websocket.md | 273 + websocket/index.ts | 40 + websocket/message-adapter.ts | 116 + websocket/message-handler.ts | 612 ++ websocket/types.ts | 290 + websocket/websocket-client.ts | 739 +++ 33 files changed, 14992 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 auth/device-guid.ts create mode 100644 auth/environments.ts create mode 100644 auth/index.ts create mode 100644 auth/qclaw-api.ts create mode 100644 auth/state-store.ts create mode 100644 auth/types.ts create mode 100644 auth/utils.ts create mode 100644 auth/wechat-login.ts create mode 100644 common/agent-events.ts create mode 100644 common/message-context.ts create mode 100644 common/runtime.ts create mode 100644 http/README.md create mode 100644 http/callback-service.ts create mode 100644 http/crypto-utils.ts create mode 100644 http/http-utils.ts create mode 100644 http/index.ts create mode 100644 http/message-context.ts create mode 100644 http/message-handler.ts create mode 100644 http/types.ts create mode 100644 http/webhook.ts create mode 100644 index.ts create mode 100644 openclaw.plugin.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 tsconfig.json create mode 100644 websocket.md create mode 100644 websocket/index.ts create mode 100644 websocket/message-adapter.ts create mode 100644 websocket/message-handler.ts create mode 100644 websocket/types.ts create mode 100644 websocket/websocket-client.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dcc4878 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +node_modules/ +dist/ +*.js +*.d.ts +*.js.map +*.d.ts.map +!jest.config.js +!vitest.config.js + +# Auth state (tokens) +.openclaw/ + +# OS +.DS_Store +Thumbs.db + +# IDE +.idea/ +.vscode/ +*.swp +*.swo diff --git a/README.md b/README.md new file mode 100644 index 0000000..7218d0b --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# wechat-access-unqclawed + +OpenClaw 微信通路插件 — 通过 WeChat OAuth 扫码登录获取 token,连接 AGP WebSocket 网关收发消息。 + +## 功能 + +- 微信扫码登录(终端二维码 + 浏览器链接) +- Token 自动持久化,重启免登录 +- AGP 协议 WebSocket 双向通信(流式文本、工具调用) +- 邀请码验证(可配置跳过) +- 支持生产/测试环境切换 + +## 安装 + +```bash +npm install +``` + +依赖 Node.js v22+,作为 OpenClaw 渠道插件运行。 + +## 配置 + +在 OpenClaw 配置文件的 `channels.wechat-access` 下: + +```json +{ + "channels": { + "wechat-access": { + "token": "", + "wsUrl": "", + "bypassInvite": false, + "environment": "production" + } + } +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `token` | string | 手动指定 channel token(留空则走扫码登录) | +| `wsUrl` | string | WebSocket 网关地址(留空则使用环境默认值) | +| `bypassInvite` | boolean | 跳过邀请码验证 | +| `environment` | string | `production` 或 `test` | +| `authStatePath` | string | 自定义 token 持久化路径 | + +## Token 获取策略 + +1. 读取配置中的 `token` — 如果有,直接使用 +2. 读取本地保存的登录态(`~/.openclaw/wechat-access-auth.json`) +3. 以上都没有 — 启动交互式微信扫码登录 + +## 项目结构 + +``` +index.ts # 插件入口,注册渠道、启停 WebSocket +auth/ + types.ts # 认证相关类型 + environments.ts # 生产/测试环境配置 + device-guid.ts # 设备 GUID 生成(随机,持久化) + qclaw-api.ts # QClaw JPRX 网关 API 客户端 + state-store.ts # Token 持久化 + wechat-login.ts # 扫码登录流程编排 +websocket/ + types.ts # AGP 协议类型 + websocket-client.ts # WebSocket 客户端(连接、心跳、重连) + message-handler.ts # 消息处理(调用 Agent) + message-adapter.ts # AGP <-> OpenClaw 消息适配 +common/ + runtime.ts # OpenClaw 运行时单例 + agent-events.ts # Agent 事件订阅 + message-context.ts # 消息上下文构建 +http/ # HTTP webhook 通道(备用) +``` + +## 协议 + +AGP (Agent Gateway Protocol) — 基于 WebSocket Text 帧的 JSON 消息协议,详见 `websocket.md`。 + +## License + +MIT diff --git a/auth/device-guid.ts b/auth/device-guid.ts new file mode 100644 index 0000000..b15ac39 --- /dev/null +++ b/auth/device-guid.ts @@ -0,0 +1,43 @@ +/** + * @file device-guid.ts + * @description 设备唯一标识生成 + * + * 不使用真实机器码,而是首次运行时随机生成一个 GUID 并持久化到本地文件。 + * 后续启动自动加载,保证同一台机器上 GUID 稳定不变。 + */ + +import { randomUUID, createHash } from "node:crypto"; +import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { homedir } from "node:os"; + +const GUID_FILE = join(homedir(), ".openclaw", "wechat-access-guid"); + +/** + * 获取设备唯一标识 + * + * 首次运行时随机生成一个 MD5 格式的 GUID 并保存到 ~/.openclaw/wechat-access-guid, + * 后续启动直接从文件读取,确保稳定。 + */ +export const getDeviceGuid = (): string => { + // 尝试从文件加载已有 GUID + try { + const existing = readFileSync(GUID_FILE, "utf-8").trim(); + if (existing) return existing; + } catch { + // 文件不存在或读取失败,继续生成 + } + + // 首次运行:生成随机 GUID(MD5 hex 格式,32 字符) + const guid = createHash("md5").update(randomUUID()).digest("hex"); + + // 持久化 + try { + mkdirSync(dirname(GUID_FILE), { recursive: true }); + writeFileSync(GUID_FILE, guid, "utf-8"); + } catch { + // 写入失败不致命,本次仍返回生成的 GUID + } + + return guid; +}; diff --git a/auth/environments.ts b/auth/environments.ts new file mode 100644 index 0000000..b25926f --- /dev/null +++ b/auth/environments.ts @@ -0,0 +1,29 @@ +/** + * @file environments.ts + * @description QClaw 环境配置(生产/测试) + */ + +import type { QClawEnvironment } from "./types.js"; + +const ENVIRONMENTS: Record = { + production: { + jprxGateway: "https://jprx.m.qq.com/", + qclawBaseUrl: "https://mmgrcalltoken.3g.qq.com/aizone/v1", + wxLoginRedirectUri: "https://security.guanjia.qq.com/login", + wechatWsUrl: "wss://mmgrcalltoken.3g.qq.com/agentwss", + wxAppId: "wx9d11056dd75b7240", + }, + test: { + jprxGateway: "https://jprx.sparta.html5.qq.com/", + qclawBaseUrl: "https://jprx.sparta.html5.qq.com/aizone/v1", + wxLoginRedirectUri: "https://security-test.guanjia.qq.com/login", + wechatWsUrl: "wss://jprx.sparta.html5.qq.com/agentwss", + wxAppId: "wx3dd49afb7e2cf957", + }, +}; + +export const getEnvironment = (name: string): QClawEnvironment => { + const env = ENVIRONMENTS[name]; + if (!env) throw new Error(`未知环境: ${name},可选: ${Object.keys(ENVIRONMENTS).join(", ")}`); + return env; +}; diff --git a/auth/index.ts b/auth/index.ts new file mode 100644 index 0000000..57532ad --- /dev/null +++ b/auth/index.ts @@ -0,0 +1,19 @@ +/** + * @file auth/index.ts + * @description 认证模块导出 + */ + +export type { + QClawEnvironment, + LoginCredentials, + PersistedAuthState, + QClawApiResponse, +} from "./types.js"; +export { TokenExpiredError } from "./types.js"; + +export { getEnvironment } from "./environments.js"; +export { getDeviceGuid } from "./device-guid.js"; +export { QClawAPI } from "./qclaw-api.js"; +export { loadState, saveState, clearState } from "./state-store.js"; +export { performLogin } from "./wechat-login.js"; +export type { PerformLoginOptions } from "./wechat-login.js"; diff --git a/auth/qclaw-api.ts b/auth/qclaw-api.ts new file mode 100644 index 0000000..c795a49 --- /dev/null +++ b/auth/qclaw-api.ts @@ -0,0 +1,129 @@ +/** + * @file qclaw-api.ts + * @description QClaw JPRX 网关 API 客户端 + * + * 对应 Python demo 的 QClawAPI 类,所有业务接口走 POST {jprxGateway}data/{cmdId}/forward。 + */ + +import type { QClawEnvironment, QClawApiResponse } from "./types.js"; +import { TokenExpiredError } from "./types.js"; +import { nested } from "./utils.js"; + +export class QClawAPI { + private env: QClawEnvironment; + private guid: string; + + /** 鉴权 key,登录后可由服务端返回新值 */ + loginKey = "m83qdao0AmE5"; + + jwtToken: string; + userId = ""; + + constructor(env: QClawEnvironment, guid: string, jwtToken = "") { + this.env = env; + this.guid = guid; + this.jwtToken = jwtToken; + } + + private headers(): Record { + const h: Record = { + "Content-Type": "application/json", + "X-Version": "1", + "X-Token": this.loginKey, + "X-Guid": this.guid, + "X-Account": this.userId || "1", + "X-Session": "", + }; + if (this.jwtToken) { + h["X-OpenClaw-Token"] = this.jwtToken; + } + return h; + } + + private async post(path: string, body: Record = {}): Promise { + const url = `${this.env.jprxGateway}${path}`; + const payload = { ...body, web_version: "1.4.0", web_env: "release" }; + + const res = await fetch(url, { + method: "POST", + headers: this.headers(), + body: JSON.stringify(payload), + signal: AbortSignal.timeout(30_000), + }); + + // Token 续期 + const newToken = res.headers.get("X-New-Token"); + if (newToken) this.jwtToken = newToken; + + const data = (await res.json()) as Record; + + const ret = data.ret; + const commonCode = + nested(data, "data", "resp", "common", "code") ?? + nested(data, "data", "common", "code") ?? + nested(data, "resp", "common", "code") ?? + nested(data, "common", "code"); + + // Token 过期 + if (commonCode === 21004) { + throw new TokenExpiredError(); + } + + if (ret === 0 || commonCode === 0) { + const respData = + nested(data, "data", "resp", "data") ?? + nested(data, "data", "data") ?? + data.data ?? + data; + return { success: true, data: respData as Record }; + } + + const message = + (nested(data, "data", "common", "message") as string) ?? + (nested(data, "resp", "common", "message") as string) ?? + (nested(data, "common", "message") as string) ?? + "请求失败"; + return { success: false, message, data: data as Record }; + } + + // ---------- 业务 API ---------- + + /** 获取微信登录 state(OAuth2 安全校验) */ + async getWxLoginState(): Promise { + return this.post("data/4050/forward", { guid: this.guid }); + } + + /** 用微信授权 code 换取 token */ + async wxLogin(code: string, state: string): Promise { + return this.post("data/4026/forward", { guid: this.guid, code, state }); + } + + /** 创建模型 API Key */ + async createApiKey(): Promise { + return this.post("data/4055/forward", {}); + } + + /** 获取用户信息 */ + async getUserInfo(): Promise { + return this.post("data/4027/forward", {}); + } + + /** 检查邀请码验证状态 */ + async checkInviteCode(userId: string): Promise { + return this.post("data/4056/forward", { user_id: userId }); + } + + /** 提交邀请码 */ + async submitInviteCode(userId: string, code: string): Promise { + return this.post("data/4057/forward", { user_id: userId, code }); + } + + /** 刷新渠道 token */ + async refreshChannelToken(): Promise { + const result = await this.post("data/4058/forward", {}); + if (result.success) { + return (result.data as Record)?.openclaw_channel_token as string ?? null; + } + return null; + } +} diff --git a/auth/state-store.ts b/auth/state-store.ts new file mode 100644 index 0000000..126455f --- /dev/null +++ b/auth/state-store.ts @@ -0,0 +1,48 @@ +/** + * @file state-store.ts + * @description 登录态持久化存储 + * + * 将 token 保存到本地文件,下次启动时自动加载,避免重复扫码。 + * 文件权限设为 0o600,仅当前用户可读写。 + */ + +import { readFileSync, writeFileSync, unlinkSync, mkdirSync, chmodSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { homedir } from "node:os"; +import type { PersistedAuthState } from "./types.js"; + +const DEFAULT_STATE_PATH = join(homedir(), ".openclaw", "wechat-access-auth.json"); + +export const getStatePath = (customPath?: string): string => + customPath || DEFAULT_STATE_PATH; + +export const loadState = (customPath?: string): PersistedAuthState | null => { + const filePath = getStatePath(customPath); + try { + const raw = readFileSync(filePath, "utf-8"); + return JSON.parse(raw) as PersistedAuthState; + } catch { + return null; + } +}; + +export const saveState = (state: PersistedAuthState, customPath?: string): void => { + const filePath = getStatePath(customPath); + mkdirSync(dirname(filePath), { recursive: true }); + writeFileSync(filePath, JSON.stringify(state, null, 2), { encoding: "utf-8", mode: 0o600 }); + // 确保已有文件也收紧权限 + try { + chmodSync(filePath, 0o600); + } catch { + // Windows 等平台可能不支持 chmod,忽略 + } +}; + +export const clearState = (customPath?: string): void => { + const filePath = getStatePath(customPath); + try { + unlinkSync(filePath); + } catch { + // file not found — ignore + } +}; diff --git a/auth/types.ts b/auth/types.ts new file mode 100644 index 0000000..f67f190 --- /dev/null +++ b/auth/types.ts @@ -0,0 +1,57 @@ +/** + * @file types.ts + * @description 微信扫码登录相关类型定义 + */ + +/** QClaw 环境配置 */ +export interface QClawEnvironment { + /** JPRX 网关地址 */ + jprxGateway: string; + /** QClaw 基础 URL (未直接使用,走 JPRX 网关) */ + qclawBaseUrl: string; + /** 微信登录回调地址 */ + wxLoginRedirectUri: string; + /** WebSocket 网关地址 */ + wechatWsUrl: string; + /** 微信开放平台 AppID */ + wxAppId: string; +} + +/** 登录凭证 */ +export interface LoginCredentials { + /** JWT Token (用于 API 鉴权) */ + jwtToken: string; + /** Channel Token (用于 WebSocket 连接) */ + channelToken: string; + /** 用户信息 */ + userInfo: Record; + /** API Key (用于调用模型) */ + apiKey: string; + /** 设备 GUID */ + guid: string; +} + +/** 持久化的登录态 */ +export interface PersistedAuthState { + jwtToken: string; + channelToken: string; + apiKey: string; + guid: string; + userInfo: Record; + savedAt: number; +} + +/** QClaw API 通用响应 */ +export interface QClawApiResponse { + success: boolean; + data?: T; + message?: string; +} + +/** Token 过期错误 */ +export class TokenExpiredError extends Error { + constructor(message = "登录已过期,请重新登录") { + super(message); + this.name = "TokenExpiredError"; + } +} diff --git a/auth/utils.ts b/auth/utils.ts new file mode 100644 index 0000000..67736d4 --- /dev/null +++ b/auth/utils.ts @@ -0,0 +1,14 @@ +/** + * @file utils.ts + * @description 认证模块共享工具函数 + */ + +/** 安全嵌套取值 */ +export const nested = (obj: unknown, ...keys: string[]): unknown => { + let current = obj; + for (const key of keys) { + if (current == null || typeof current !== "object") return undefined; + current = (current as Record)[key]; + } + return current; +}; diff --git a/auth/wechat-login.ts b/auth/wechat-login.ts new file mode 100644 index 0000000..9d84f02 --- /dev/null +++ b/auth/wechat-login.ts @@ -0,0 +1,238 @@ +/** + * @file wechat-login.ts + * @description 微信扫码登录流程编排 + * + * 对应 Python demo 的 WeChatLogin 类和 do_login 函数。 + * 流程:获取 state → 生成二维码 → 等待 code → 换 token → (邀请码) → 保存 + */ + +import { createInterface } from "node:readline"; +import type { QClawEnvironment, LoginCredentials, PersistedAuthState } from "./types.js"; +import { QClawAPI } from "./qclaw-api.js"; +import { saveState } from "./state-store.js"; +import { nested } from "./utils.js"; + +/** 构造微信 OAuth2 授权 URL */ +const buildAuthUrl = (state: string, env: QClawEnvironment): string => { + const params = new URLSearchParams({ + appid: env.wxAppId, + redirect_uri: env.wxLoginRedirectUri, + response_type: "code", + scope: "snsapi_login", + state, + }); + return `https://open.weixin.qq.com/connect/qrconnect?${params.toString()}#wechat_redirect`; +}; + +/** 在终端显示二维码 */ +const displayQrCode = async (url: string): Promise => { + console.log("\n" + "=".repeat(60)); + console.log(" 请用微信扫描下方二维码登录"); + console.log("=".repeat(60)); + + try { + // qrcode-terminal 是 CJS 模块,动态 import + const qrterm = await import("qrcode-terminal"); + const generate = qrterm.default?.generate ?? qrterm.generate; + generate(url, { small: true }, (qrcode: string) => { + console.log(qrcode); + }); + } catch { + console.log("\n(未安装 qrcode-terminal,无法在终端显示二维码)"); + console.log("请安装: npm install qrcode-terminal"); + } + + console.log("\n或者在浏览器中打开以下链接:"); + console.log(` ${url}`); + console.log("=".repeat(60)); +}; + +/** 从 stdin 读取一行 */ +const readLine = (prompt: string): Promise => { + const rl = createInterface({ input: process.stdin, output: process.stdout }); + return new Promise((resolve) => { + rl.question(prompt, (answer) => { + rl.close(); + resolve(answer.trim()); + }); + }); +}; + +/** + * 等待用户输入微信授权后重定向 URL 中的 code + * + * 接受两种输入: + * 1. 完整 URL(自动从 query string 或 fragment 提取 code) + * 2. 裸 code 字符串 + */ +const waitForAuthCode = async (): Promise => { + console.log(); + console.log("微信扫码授权后,浏览器会跳转到一个新页面。"); + console.log("请从浏览器地址栏复制完整 URL,或只复制 code 参数值。"); + console.log(); + + const raw = await readLine("请粘贴 URL 或 code: "); + if (!raw) return ""; + + // 尝试从 URL 中提取 code + if (raw.includes("code=")) { + try { + const url = new URL(raw); + // 先查 query string + const code = url.searchParams.get("code"); + if (code) return code; + // 再查 fragment(微信可能将 code 放在 hash 后面) + if (url.hash) { + const fragmentParams = new URLSearchParams(url.hash.replace(/^#/, "")); + const fCode = fragmentParams.get("code"); + if (fCode) return fCode; + } + } catch { + // URL 解析失败,尝试正则 + } + const match = raw.match(/[?&#]code=([^&#]+)/); + if (match?.[1]) return match[1]; + } + + // 直接就是 code + return raw; +}; + +export interface PerformLoginOptions { + guid: string; + env: QClawEnvironment; + bypassInvite?: boolean; + /** 自定义 state 文件路径 */ + authStatePath?: string; + /** 日志函数 */ + log?: { info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void }; +} + +/** + * 执行完整的微信扫码登录流程 + * + * 步骤: + * 1. 获取 OAuth state + * 2. 生成二维码并展示 + * 3. 等待用户输入 code + * 4. 用 code 换 token + * 5. 创建 API Key(非致命) + * 6. 邀请码检查(可绕过) + * 7. 保存登录态 + */ +export const performLogin = async (options: PerformLoginOptions): Promise => { + const { guid, env, bypassInvite = false, authStatePath, log } = options; + const info = (...args: unknown[]) => log?.info?.(...args) ?? console.log(...args); + const warn = (...args: unknown[]) => log?.warn?.(...args) ?? console.warn(...args); + + const api = new QClawAPI(env, guid); + + // 1. 获取 OAuth state + info("[Login] 步骤 1/5: 获取登录 state..."); + let state = String(Math.floor(Math.random() * 10000)); // 随机兜底 + const stateResult = await api.getWxLoginState(); + if (stateResult.success) { + const s = nested(stateResult.data, "state") as string | undefined; + if (s) state = s; + } + info(`[Login] state=${state}`); + + // 2. 生成二维码 + info("[Login] 步骤 2/5: 生成微信登录二维码..."); + const authUrl = buildAuthUrl(state, env); + await displayQrCode(authUrl); + + // 3. 等待 code + info("[Login] 步骤 3/5: 等待微信扫码授权..."); + const code = await waitForAuthCode(); + if (!code) { + throw new Error("未获取到授权 code"); + } + + // 4. 用 code 换 token + info(`[Login] 步骤 4/5: 用授权码登录 (code=${code.substring(0, 10)}...)`); + const loginResult = await api.wxLogin(code, state); + if (!loginResult.success) { + throw new Error(`登录失败: ${loginResult.message ?? "未知错误"}`); + } + + const loginData = loginResult.data as Record; + const jwtToken = (loginData.token as string) || ""; + const channelToken = (loginData.openclaw_channel_token as string) || ""; + const userInfo = (loginData.user_info as Record) || {}; + + api.jwtToken = jwtToken; + api.userId = String(userInfo.user_id ?? ""); + // 更新 loginKey(服务端可能返回新值,后续 API 调用需要使用) + const loginKey = userInfo.loginKey as string | undefined; + if (loginKey) { + api.loginKey = loginKey; + } + + info(`[Login] 登录成功! 用户: ${(userInfo.nickname as string) ?? "unknown"}`); + + // 5. 创建 API Key(非致命) + info("[Login] 步骤 5/5: 创建 API Key..."); + let apiKey = ""; + try { + const keyResult = await api.createApiKey(); + if (keyResult.success) { + apiKey = + (nested(keyResult.data, "key") as string) ?? + (nested(keyResult.data, "resp", "data", "key") as string) ?? + ""; + if (apiKey) info(`[Login] API Key: ${apiKey.substring(0, 8)}...`); + } + } catch (e) { + warn(`[Login] 创建 API Key 失败(非致命): ${e}`); + } + + // 邀请码检查 + const userId = String(userInfo.user_id ?? ""); + if (userId && !bypassInvite) { + try { + const check = await api.checkInviteCode(userId); + if (check.success) { + const verified = nested(check.data, "already_verified"); + if (!verified) { + info("\n[Login] 需要邀请码验证。"); + const inviteCode = await readLine("请输入邀请码: "); + if (inviteCode) { + const submitResult = await api.submitInviteCode(userId, inviteCode); + if (!submitResult.success) { + throw new Error(`邀请码验证失败: ${submitResult.message}`); + } + info("[Login] 邀请码验证通过!"); + } + } + } + } catch (e) { + if (e instanceof Error && e.message.includes("邀请码验证失败")) throw e; + warn(`[Login] 邀请码检查失败(非致命): ${e}`); + } + } else if (bypassInvite) { + info("[Login] 已跳过邀请码验证 (bypassInvite=true)"); + } + + // 保存登录态 + const credentials: LoginCredentials = { + jwtToken, + channelToken, + userInfo, + apiKey, + guid, + }; + + const persistedState: PersistedAuthState = { + jwtToken, + channelToken, + apiKey, + guid, + userInfo, + savedAt: Date.now(), + }; + saveState(persistedState, authStatePath); + info("[Login] 登录态已保存"); + + return credentials; +}; diff --git a/common/agent-events.ts b/common/agent-events.ts new file mode 100644 index 0000000..91fcaa5 --- /dev/null +++ b/common/agent-events.ts @@ -0,0 +1,49 @@ +import type { onAgentEvent as OnAgentEventType } from "openclaw/plugin-sdk"; + +export type AgentEventStream = "lifecycle" | "tool" | "assistant" | "error" | (string & {}); + +export type AgentEventPayload = { + runId: string; + seq: number; + stream: AgentEventStream; + ts: number; + data: Record; + sessionKey?: string; +}; + +// 动态导入,兼容 openclaw 未导出该函数的情况 +let _onAgentEvent: typeof OnAgentEventType | undefined; + +// SDK 加载完成的 Promise,确保只加载一次 +const sdkReady: Promise = (async () => { + try { + const sdk = await import("openclaw/plugin-sdk"); + if (typeof sdk.onAgentEvent === "function") { + _onAgentEvent = sdk.onAgentEvent; + } + } catch { + // ignore + } + return _onAgentEvent; +})(); + +/** + * 注册 Agent 事件监听器。 + * + * 修复了原版的时序问题:原版使用 loadOnAgentEvent().then() 异步注册, + * 导致在 dispatchReplyWithBufferedBlockDispatcher 调用之前注册的监听器 + * 实际上在 Agent 开始产生事件时还未真正挂载,造成事件全部丢失。 + * + * 新版通过 await sdkReady 确保 SDK 加载完成后再注册监听器, + * 调用方需要 await 此函数返回的 Promise,再调用 dispatchReply。 + */ +export const onAgentEvent = async ( + listener: Parameters[0] +): Promise<() => boolean> => { + const fn = await sdkReady; + if (fn) { + const unsubscribe = fn(listener); + return unsubscribe; + } + return () => false; +}; \ No newline at end of file diff --git a/common/message-context.ts b/common/message-context.ts new file mode 100644 index 0000000..be8986c --- /dev/null +++ b/common/message-context.ts @@ -0,0 +1,174 @@ +import type { FuwuhaoMessage } from "../http/types.js"; +import { getWecomRuntime } from "./runtime.js"; + +// ============================================ +// 渠道来源标签 +// ============================================ +// 用于 ChannelSource,标识消息来自哪个微信渠道 +// UI 侧可通过此字段区分不同来源,做差异化展示或交互限制 +export const WECHAT_CHANNEL_LABELS = { + /** 微信服务号 */ + serviceAccount: "serviceAccount", + /** 微信小程序 */ + miniProgram: "miniProgram", +} as const; + +// ============================================ +// 消息上下文构建 +// ============================================ +// 将微信服务号的原始消息转换为 OpenClaw 标准的消息上下文 +// 包括路由解析、会话管理、消息格式化等核心功能 + +/** + * 消息上下文返回类型 + * @property ctx - OpenClaw 标准的消息上下文对象,包含所有必要的消息元数据 + * @property route - 路由信息,用于确定消息应该发送到哪个 Agent + * @property storePath - 会话存储路径,用于持久化会话数据 + */ +export interface MessageContext { + ctx: Record; + route: { + sessionKey: string; // 会话唯一标识,用于关联同一用户的多轮对话 + agentId: string; // Agent ID,标识处理此消息的 Agent + accountId: string; // 账号 ID,用于多账号场景 + }; + storePath: string; +} + +/** + * 构建消息上下文 + * @param message - 微信服务号的原始消息对象 + * @returns MessageContext 包含上下文、路由和存储路径的完整消息上下文 + * @description + * 此函数是消息处理的核心,负责: + * 1. 提取和标准化消息字段(兼容多种格式) + * 2. 解析路由,确定消息应该发送到哪个 Agent + * 3. 获取会话存储路径,用于持久化对话历史 + * 4. 格式化消息为 OpenClaw 标准格式 + * 5. 构建完整的消息上下文对象 + * + * 内部流程: + * - 从 runtime 获取配置 + * - 提取用户 ID、消息 ID、内容等关键信息 + * - 调用 routing.resolveAgentRoute 解析路由 + * - 调用 session.resolveStorePath 获取存储路径 + * - 调用 reply.formatInboundEnvelope 格式化消息 + * - 调用 reply.finalizeInboundContext 构建最终上下文 + */ +export const buildMessageContext = (message: FuwuhaoMessage): MessageContext => { + // 获取 OpenClaw 运行时实例 + const runtime = getWecomRuntime(); + // 加载全局配置(包含 Agent 配置、路由规则等) + const cfg = runtime.config.loadConfig(); + + // ============================================ + // 1. 提取和标准化消息字段 + // ============================================ + // 兼容多种字段命名(FromUserName/userid) + const userId = message.FromUserName || message.userid || "unknown"; + const toUser = message.ToUserName || "unknown"; + // 确保消息 ID 唯一(用于去重和追踪) + const messageId = message.MsgId || message.msgid || `${Date.now()}`; + // TODO: 微信的 CreateTime 是秒级时间戳,需要转换为毫秒 + // const timestamp = message.CreateTime ? message.CreateTime * 1000 : Date.now(); + const timestamp = Date.now(); + // 提取消息内容(兼容 Content 和 text.content 两种格式) + const content = message.Content || message.text?.content || ""; + + // ============================================ + // 2. 解析路由 - 确定消息应该发送到哪个 Agent + // ============================================ + // runtime.channel.routing.resolveAgentRoute 是 OpenClaw 的核心路由方法 + // 根据频道、账号、对话类型等信息,决定使用哪个 Agent 处理消息 + const frameworkRoute = runtime.channel.routing.resolveAgentRoute({ + cfg, // 全局配置 + channel: "wechat-access", // 频道标识 + accountId: "default", // 账号 ID(支持多账号场景) + peer: { + kind: "dm", // 对话类型:dm=私聊,group=群聊 + id: userId, // 对话对象 ID(用户 ID) + }, + }); + // 框架返回的 sessionKey 通常是 agent:main:main,与 PC 端默认 session 相同。 + // 为了让 UI 能区分外部渠道消息,使用独立的 sessionKey 格式: + // agent:{agentId}:wechat-access:direct:{userId} + const channelSessionKey = `agent:${frameworkRoute.agentId}:wechat-access:direct:${userId}`; + const route = { + ...frameworkRoute, + sessionKey: channelSessionKey, + }; + + // ============================================ + // 3. 获取消息格式化选项 + // ============================================ + // runtime.channel.reply.resolveEnvelopeFormatOptions 获取消息格式化配置 + // 包括时间格式、前缀、后缀等显示选项 + const envelopeOptions = runtime.channel.reply.resolveEnvelopeFormatOptions(cfg); + + // ============================================ + // 4. 获取会话存储路径 + // ============================================ + // runtime.channel.session.resolveStorePath 计算会话数据的存储路径 + // 用于持久化对话历史、上下文等信息 + const storePath = runtime.channel.session.resolveStorePath(cfg.session?.store, { + agentId: route.agentId, + }); + // 存储路径通常类似:/data/sessions/{agentId}/{sessionKey}.json + + // ============================================ + // 5. 读取上次会话时间 + // ============================================ + // runtime.channel.session.readSessionUpdatedAt 读取上次会话的更新时间 + // 用于判断会话是否过期,是否需要重置上下文 + const previousTimestamp = runtime.channel.session.readSessionUpdatedAt({ + storePath, + sessionKey: route.sessionKey, + }); + // 如果距离上次会话时间过长,可能会清空历史上下文 + + // ============================================ + // 6. 格式化入站消息 + // ============================================ + // runtime.channel.reply.formatInboundEnvelope 将原始消息格式化为标准格式 + // 添加时间戳、发送者信息、格式化选项等 + const body = runtime.channel.reply.formatInboundEnvelope({ + channel: "wechat-access", // 频道标识 + from: userId, // 发送者 ID + timestamp, // 消息时间戳 + body: content, // 消息内容 + chatType: "direct", // 对话类型(direct=私聊) + sender: { + id: userId, // 发送者 ID + }, + previousTimestamp, // 上次会话时间(用于判断是否需要添加时间分隔符) + envelope: envelopeOptions, // 格式化选项 + }); + // 返回格式化后的消息体,可能包含时间前缀、发送者名称等 + + // ============================================ + // 7. 构建完整的消息上下文 + // ============================================ + // runtime.channel.reply.finalizeInboundContext 构建 OpenClaw 标准的消息上下文 + // 这是 Agent 处理消息时使用的核心数据结构 + const ctx = runtime.channel.reply.finalizeInboundContext({ + Body: body, // 格式化后的消息体 + RawBody: content, // 原始消息内容 + CommandBody: content, // 命令体(用于解析命令) + From: `wechat-access:${userId}`, // 发送者标识(带频道前缀) + To: `wechat-access:${toUser}`, // 接收者标识 + SessionKey: route.sessionKey, // 会话键 + AccountId: route.accountId, // 账号 ID + ChatType: "direct" as const, // 对话类型 + ChannelSource: WECHAT_CHANNEL_LABELS.serviceAccount, // 渠道来源标识(用于 UI 侧区分消息来源) + SenderId: userId, // 发送者 ID + Provider: "wechat-access", // 提供商标识 + Surface: "wechat-access", // 界面标识 + MessageSid: messageId, // 消息唯一标识 + Timestamp: timestamp, // 时间戳 + OriginatingChannel: "wechat-access" as const, // 原始频道 + OriginatingTo: `wechat-access:${userId}`, // 原始接收者 + }); + // ctx 包含了 Agent 处理消息所需的所有信息 + + return { ctx, route, storePath }; +}; diff --git a/common/runtime.ts b/common/runtime.ts new file mode 100644 index 0000000..b5985cf --- /dev/null +++ b/common/runtime.ts @@ -0,0 +1,35 @@ +import type { PluginRuntime } from "openclaw/plugin-sdk"; + +// ============================================ +// Runtime 管理 +// ============================================ +// 用于存储和获取 OpenClaw 的运行时实例 +// Runtime 提供了访问配置、会话、路由、事件等核心功能的接口 + +/** + * 全局运行时实例 + * 在插件初始化时由 OpenClaw 框架注入 + */ +let runtime: PluginRuntime | null = null; + +/** + * 设置微信企业号运行时实例 + * @param next - OpenClaw 提供的运行时实例 + * @description 此方法应在插件初始化时调用一次,用于注入运行时依赖 + */ +export const setWecomRuntime = (next: PluginRuntime): void => { + runtime = next; +}; + +/** + * 获取微信企业号运行时实例 + * @returns OpenClaw 运行时实例 + * @throws 如果运行时未初始化则抛出错误 + * @description 在需要访问 OpenClaw 核心功能时调用此方法 + */ +export const getWecomRuntime = (): PluginRuntime => { + if (!runtime) { + throw new Error("WeCom runtime not initialized"); + } + return runtime; +}; \ No newline at end of file diff --git a/http/README.md b/http/README.md new file mode 100644 index 0000000..b7d040a --- /dev/null +++ b/http/README.md @@ -0,0 +1,138 @@ +# Fuwuhao (微信服务号) 模块 + +## 📁 文件结构 + +``` +src/ +├── types.ts # 类型定义 +├── crypto-utils.ts # 加密解密工具 +├── http-utils.ts # HTTP 请求处理工具 +├── callback-service.ts # 后置回调服务 +├── message-context.ts # 消息上下文构建 +├── message-handler.ts # 消息处理器(核心业务逻辑) +├── webhook.ts # Webhook 处理器(主入口) +├── runtime.ts # Runtime 配置 +└── index.ts # 模块导出索引 +``` + +## 📦 模块说明 + +### 1. `types.ts` - 类型定义 +定义所有 TypeScript 类型和接口: +- `AgentEventPayload` - Agent 事件载荷 +- `FuwuhaoMessage` - 服务号消息格式 +- `SimpleAccount` - 账号配置 +- `CallbackPayload` - 回调数据格式 +- `StreamChunk` - 流式消息块 +- `StreamCallback` - 流式回调函数类型 + +### 2. `crypto-utils.ts` - 加密解密工具 +处理微信服务号的签名验证和消息加密解密: +- `verifySignature()` - 验证签名 +- `decryptMessage()` - 解密消息 + +### 3. `http-utils.ts` - HTTP 工具 +处理 HTTP 请求相关的工具方法: +- `parseQuery()` - 解析查询参数 +- `readBody()` - 读取请求体 +- `isFuwuhaoWebhookPath()` - 检查是否是服务号 webhook 路径 + +### 4. `callback-service.ts` - 后置回调服务 +将处理结果发送到外部回调服务: +- `sendToCallbackService()` - 发送回调数据 + +### 5. `message-context.ts` - 消息上下文构建 +构建消息处理所需的上下文信息: +- `buildMessageContext()` - 构建消息上下文(路由、会话、格式化等) + +### 6. `message-handler.ts` - 消息处理器 +核心业务逻辑,处理消息并调用 Agent: +- `handleMessage()` - 同步处理消息 +- `handleMessageStream()` - 流式处理消息(SSE) + +### 7. `webhook.ts` - Webhook 处理器 +主入口,处理微信服务号的 webhook 请求: +- `handleSimpleWecomWebhook()` - 处理 GET/POST 请求,支持同步和流式返回 + +### 8. `runtime.ts` - Runtime 配置 +获取 OpenClaw 运行时实例 + +### 9. `index.ts` - 模块导出 +统一导出所有公共 API + +## 🔄 数据流 + +``` +微信服务号 + ↓ +webhook.ts (入口) + ↓ +http-utils.ts (解析请求) + ↓ +crypto-utils.ts (验证签名/解密) + ↓ +message-context.ts (构建上下文) + ↓ +message-handler.ts (处理消息) + ↓ +OpenClaw Agent (AI 处理) + ↓ +callback-service.ts (后置回调) + ↓ +返回响应 +``` + +## 🚀 使用示例 + +### 基本使用 +```typescript +import { handleSimpleWecomWebhook } from "./src/webhook.js"; + +// 在 HTTP 服务器中使用 +server.on("request", async (req, res) => { + const handled = await handleSimpleWecomWebhook(req, res); + if (!handled) { + // 处理其他路由 + } +}); +``` + +### 流式返回(SSE) +```typescript +// 客户端请求时添加 stream 参数 +fetch("/fuwuhao?stream=true", { + headers: { + "Accept": "text/event-stream" + } +}); +``` + +## 🔧 配置 + +### 环境变量 +- `FUWUHAO_CALLBACK_URL` - 后置回调服务 URL(默认:`http://localhost:3001/api/fuwuhao/callback`) + +### 账号配置 +在 `webhook.ts` 中修改 `mockAccount` 对象: +```typescript +const mockAccount: SimpleAccount = { + token: "your_token_here", + encodingAESKey: "your_encoding_aes_key_here", + receiveId: "your_receive_id_here" +}; +``` + +## 📝 注意事项 + +1. **加密解密**:当前 `crypto-utils.ts` 中的加密解密方法是简化版,生产环境需要实现真实的加密逻辑 +2. **签名验证**:同样需要在生产环境中实现真实的签名验证算法 +3. **错误处理**:所有模块都包含完善的错误处理和日志记录 +4. **类型安全**:所有模块都使用 TypeScript 严格类型检查 + +## 🎯 设计原则 + +- **单一职责**:每个文件只负责一个特定功能 +- **低耦合**:模块之间通过明确的接口通信 +- **高内聚**:相关功能集中在同一模块 +- **可测试**:每个模块都可以独立测试 +- **可扩展**:易于添加新功能或修改现有功能 diff --git a/http/callback-service.ts b/http/callback-service.ts new file mode 100644 index 0000000..2b24f01 --- /dev/null +++ b/http/callback-service.ts @@ -0,0 +1,73 @@ +import type { CallbackPayload } from "./types.js"; + +// ============================================ +// 后置回调服务 +// ============================================ +// 用于将消息处理结果发送到外部服务进行后续处理 +// 例如:数据统计、日志记录、业务逻辑触发等 + +/** + * 后置回调服务的 URL 地址 + * @description + * 可通过环境变量 WECHAT_ACCESS_CALLBACK_URL 配置 + * 默认值:http://localhost:3001/api/wechat-access/callback + */ +const CALLBACK_SERVICE_URL = process.env.WECHAT_ACCESS_CALLBACK_URL || "http://localhost:3001/api/wechat-access/callback"; + +/** + * 发送消息处理结果到后置回调服务 + * @param payload - 回调数据载荷,包含用户消息、AI 回复、会话信息等 + * @returns Promise 异步执行,不阻塞主流程 + * @description + * 后置回调的作用: + * 1. 记录消息处理日志 + * 2. 统计用户交互数据 + * 3. 触发业务逻辑(如积分、通知等) + * 4. 数据分析和监控 + * + * 特点: + * - 异步执行,失败不影响主流程 + * - 支持自定义认证(通过 Authorization header) + * - 自动处理错误,只记录日志 + * @example + * await sendToCallbackService({ + * userId: 'user123', + * messageId: 'msg456', + * userMessage: '你好', + * aiReply: '您好!有什么可以帮您?', + * success: true + * }); + */ +export const sendToCallbackService = async (payload: CallbackPayload): Promise => { + try { + console.log("[wechat-access] 发送后置回调:", { + url: CALLBACK_SERVICE_URL, + userId: payload.userId, + hasReply: !!payload.aiReply, + }); + + const response = await fetch(CALLBACK_SERVICE_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + // 可以添加认证头 + // "Authorization": `Bearer ${process.env.CALLBACK_AUTH_TOKEN}`, + }, + body: JSON.stringify(payload), + }); + + if (!response.ok) { + console.error("[wechat-access] 后置回调服务返回错误:", { + status: response.status, + statusText: response.statusText, + }); + return; + } + + const result = await response.json().catch(() => ({})); + console.log("[wechat-access] 后置回调成功:", result); + } catch (err) { + // 后置回调失败不影响主流程,只记录日志 + console.error("[wechat-access] 后置回调失败:", err); + } +}; diff --git a/http/crypto-utils.ts b/http/crypto-utils.ts new file mode 100644 index 0000000..96e5278 --- /dev/null +++ b/http/crypto-utils.ts @@ -0,0 +1,96 @@ +// ============================================ +// 加密解密工具 +// ============================================ +// 处理微信服务号的消息加密、解密和签名验证 +// 微信使用 AES-256-CBC 加密算法和 SHA-1 签名算法 + +/** + * 验证签名参数接口 + * @property token - 微信服务号配置的 Token + * @property timestamp - 时间戳 + * @property nonce - 随机数 + * @property encrypt - 加密的消息内容 + * @property signature - 微信生成的签名,用于验证消息来源 + */ +export interface VerifySignatureParams { + token: string; + timestamp: string; + nonce: string; + encrypt: string; + signature: string; +} + +/** + * 解密消息参数接口 + * @property encodingAESKey - 微信服务号配置的 EncodingAESKey(43位字符) + * @property receiveId - 接收方 ID(通常是服务号的原始 ID) + * @property encrypt - 加密的消息内容(Base64 编码) + */ +export interface DecryptMessageParams { + encodingAESKey: string; + receiveId: string; + encrypt: string; +} + +/** + * 验证微信消息签名 + * @param params - 签名验证参数 + * @returns 签名是否有效 + * @description + * 验证流程: + * 1. 将 token、timestamp、nonce、encrypt 按字典序排序 + * 2. 拼接成字符串 + * 3. 进行 SHA-1 哈希 + * 4. 与微信提供的 signature 比对 + * + * **注意:当前为简化实现,生产环境需要实现真实的 SHA-1 签名验证** + */ +export const verifySignature = (params: VerifySignatureParams): boolean => { + // TODO: 实现真实的签名验证逻辑 + // 参考算法: + // const arr = [params.token, params.timestamp, params.nonce, params.encrypt].sort(); + // const str = arr.join(''); + // const hash = crypto.createHash('sha1').update(str).digest('hex'); + // return hash === params.signature; + + console.log("[wechat-access] 验证签名参数:", params); + return true; // 简化实现,直接返回 true +}; + +/** + * 解密微信消息 + * @param params - 解密参数 + * @returns 解密后的明文消息(JSON 字符串) + * @description + * 解密流程: + * 1. 将 Base64 编码的 encrypt 解码为二进制 + * 2. 使用 AES-256-CBC 算法解密(密钥由 encodingAESKey 派生) + * 3. 去除填充(PKCS7) + * 4. 提取消息内容(格式:随机16字节 + 4字节消息长度 + 消息内容 + receiveId) + * 5. 验证 receiveId 是否匹配 + * + * **注意:当前为简化实现,返回模拟数据,生产环境需要实现真实的 AES 解密** + */ +export const decryptMessage = (params: DecryptMessageParams): string => { + // TODO: 实现真实的解密逻辑 + // 参考算法: + // const key = Buffer.from(params.encodingAESKey + '=', 'base64'); + // const iv = key.slice(0, 16); + // const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); + // decipher.setAutoPadding(false); + // let decrypted = Buffer.concat([decipher.update(params.encrypt, 'base64'), decipher.final()]); + // // 去除 PKCS7 填充 + // const pad = decrypted[decrypted.length - 1]; + // decrypted = decrypted.slice(0, decrypted.length - pad); + // // 提取消息内容 + // const content = decrypted.slice(16); + // const msgLen = content.readUInt32BE(0); + // const message = content.slice(4, 4 + msgLen).toString('utf8'); + // const receiveId = content.slice(4 + msgLen).toString('utf8'); + // if (receiveId !== params.receiveId) throw new Error('receiveId mismatch'); + // return message; + + console.log("[wechat-access] 解密参数:", params); + // 返回模拟的解密结果(标准微信消息格式) + return '{"msgtype":"text","Content":"Hello from 服务号","MsgId":"123456","FromUserName":"user001","ToUserName":"gh_test","CreateTime":1234567890}'; +}; diff --git a/http/http-utils.ts b/http/http-utils.ts new file mode 100644 index 0000000..1d897a5 --- /dev/null +++ b/http/http-utils.ts @@ -0,0 +1,81 @@ +import type { IncomingMessage } from "node:http"; + +// ============================================ +// HTTP 工具方法 +// ============================================ +// 提供 HTTP 请求处理的通用工具函数 + +/** + * 解析 URL 查询参数 + * @param req - Node.js HTTP 请求对象 + * @returns URLSearchParams 对象,可通过 get() 方法获取参数值 + * @description + * 从请求 URL 中提取查询参数,例如: + * - /wechat-access?timestamp=123&nonce=abc + * - 可通过 params.get('timestamp') 获取值 + * @example + * const query = parseQuery(req); + * const timestamp = query.get('timestamp'); + */ +export const parseQuery = (req: IncomingMessage): URLSearchParams => { + const url = new URL(req.url || "", `http://${req.headers.host}`); + return url.searchParams; +}; + +/** + * 读取 HTTP 请求体内容 + * @param req - Node.js HTTP 请求对象 + * @returns Promise 请求体的完整内容(字符串格式) + * @description + * 异步读取请求体的所有数据块,适用于: + * - POST 请求的 JSON 数据 + * - XML 格式的微信消息 + * - 表单数据 + * + * 内部实现: + * 1. 监听 'data' 事件,累积数据块 + * 2. 监听 'end' 事件,返回完整内容 + * 3. 监听 'error' 事件,处理读取错误 + * @example + * const body = await readBody(req); + * const data = JSON.parse(body); + */ +export const readBody = async (req: IncomingMessage): Promise => { + return new Promise((resolve, reject) => { + let body = ""; + // 监听数据块事件,累积内容 + req.on("data", (chunk) => { + body += chunk.toString(); + }); + // 监听结束事件,返回完整内容 + req.on("end", () => { + resolve(body); + }); + // 监听错误事件 + req.on("error", reject); + }); +}; + +/** + * 检查请求路径是否是服务号 webhook 路径 + * @param url - 请求的完整 URL 或路径 + * @returns 是否匹配服务号 webhook 路径 + * @description + * 支持多种路径格式: + * - /wechat-access - 基础路径 + * - /wechat-access/webhook - 标准 webhook 路径 + * - /wechat-access/* - 任何以 /wechat-access/ 开头的路径 + * + * 用于路由判断,确保只处理服务号相关的请求 + * @example + * if (isFuwuhaoWebhookPath(req.url)) { + * // 处理服务号消息 + * } + */ +export const isFuwuhaoWebhookPath = (url: string): boolean => { + const pathname = new URL(url, "http://localhost").pathname; + // 支持多种路径格式 + return pathname === "/wechat-access" || + pathname === "/wechat-access/webhook" || + pathname.startsWith("/wechat-access/"); +}; diff --git a/http/index.ts b/http/index.ts new file mode 100644 index 0000000..8eb68f4 --- /dev/null +++ b/http/index.ts @@ -0,0 +1,59 @@ +// ============================================ +// Fuwuhao (微信服务号) 模块导出 +// ============================================ + +// 类型定义 +export type { + AgentEventPayload, + FuwuhaoMessage, + SimpleAccount, + CallbackPayload, + StreamChunk, + StreamCallback, +} from "./types.js"; + +// 加密解密工具 +export type { + VerifySignatureParams, + DecryptMessageParams, +} from "./crypto-utils.js"; +export { + verifySignature, + decryptMessage, +} from "./crypto-utils.js"; + +// HTTP 工具 +export { + parseQuery, + readBody, + isFuwuhaoWebhookPath, +} from "./http-utils.js"; + +// 回调服务 +export { + sendToCallbackService, +} from "./callback-service.js"; + +// 消息上下文 +export type { + MessageContext, +} from "./message-context.js"; +export { + buildMessageContext, +} from "./message-context.js"; + +// 消息处理器 +export { + handleMessage, + handleMessageStream, +} from "./message-handler.js"; + +// Webhook 处理器(主入口) +export { + handleSimpleWecomWebhook, +} from "./webhook.js"; + +// Runtime +export { + getWecomRuntime, +} from "../common/runtime.js"; diff --git a/http/message-context.ts b/http/message-context.ts new file mode 100644 index 0000000..bc35280 --- /dev/null +++ b/http/message-context.ts @@ -0,0 +1,4 @@ +// 已迁移至 common/message-context.ts +// 此文件保留以兼容现有 http 模块内部引用 +export type { MessageContext } from "../common/message-context.js"; +export { buildMessageContext, WECHAT_CHANNEL_LABELS } from "../common/message-context.js"; diff --git a/http/message-handler.ts b/http/message-handler.ts new file mode 100644 index 0000000..60031b4 --- /dev/null +++ b/http/message-handler.ts @@ -0,0 +1,560 @@ +import type { FuwuhaoMessage, CallbackPayload, StreamCallback } from "./types.js"; +import { onAgentEvent, type AgentEventPayload } from "../common/agent-events.js"; +import { getWecomRuntime } from "../common/runtime.js"; +import { buildMessageContext } from "./message-context.js"; + +/** 内容安全审核拦截标记,由 content-security 插件的 fetch 拦截器嵌入伪 SSE 响应中 */ +const SECURITY_BLOCK_MARKER = ""; + +/** 安全拦截后返回给微信用户的通用提示文本(不暴露具体拦截原因) */ +const SECURITY_BLOCK_USER_MESSAGE = "抱歉,我无法处理该任务,让我们换个任务试试看?"; + +// ============================================ +// 工具函数 +// ============================================ + +/** + * 移除 LLM 输出中泄漏的 thinking 标签及其内容 + * 兼容 kimi-k2.5 等模型在 streaming 时 ... 边界不稳定的问题 + */ +const stripThinkingTags = (text: string): string => { + return text + .replace(/<\s*think(?:ing)?\s*>[\s\S]*?<\s*\/\s*think(?:ing)?\s*>/gi, "") + .replace(/<\s*\/\s*think(?:ing)?\s*>/gi, "") // 移除孤立的结束标签 + .trim(); +}; + +// ============================================ +// 消息处理器 +// ============================================ +// 负责处理微信服务号消息并调用 OpenClaw Agent +// 支持同步和流式两种处理模式 + +/** + * 处理消息并转发给 Agent(同步模式) + * @param message - 微信服务号的原始消息对象 + * @returns Promise Agent 生成的回复文本,失败时返回 null + * @description + * 同步处理流程: + * 1. 提取消息基本信息(用户 ID、消息 ID、内容等) + * 2. 构建消息上下文(调用 buildMessageContext) + * 3. 记录会话元数据和频道活动 + * 4. 调用 Agent 处理消息(dispatchReplyWithBufferedBlockDispatcher) + * 5. 收集 Agent 的回复(通过 deliver 回调) + * 6. 返回最终回复文本 + * + * 内部关键方法: + * - runtime.channel.session.recordSessionMetaFromInbound: 记录会话元数据 + * - runtime.channel.activity.record: 记录频道活动统计 + * - runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher: 分发消息到 Agent + * - deliver 回调: 接收 Agent 的回复(block/tool/final 三种类型) + */ +export const handleMessage = async (message: FuwuhaoMessage): Promise => { + const runtime = getWecomRuntime(); + const cfg = runtime.config.loadConfig(); + + // ============================================ + // 1. 提取消息基本信息 + // ============================================ + const content = message.Content || message.text?.content || ""; + const userId = message.FromUserName || message.userid || "unknown"; + const messageId = String(message.MsgId || message.msgid || Date.now()); + const messageType = message.msgtype || "text"; + const timestamp = message.CreateTime || Date.now(); + + console.log("[wechat-access] 收到消息:", { + 类型: messageType, + 消息ID: messageId, + 内容: content, + 用户ID: userId, + 时间戳: timestamp + }); + + // ============================================ + // 2. 构建消息上下文 + // ============================================ + // buildMessageContext 将微信消息转换为 OpenClaw 标准格式 + // 返回:ctx(消息上下文)、route(路由信息)、storePath(存储路径) + const { ctx, route, storePath } = buildMessageContext(message); + + console.log("[wechat-access] 路由信息:", { + sessionKey: route.sessionKey, + agentId: route.agentId, + accountId: route.accountId, + }); + + // ============================================ + // 3. 记录会话元数据 + // ============================================ + // runtime.channel.session.recordSessionMetaFromInbound 记录会话的元数据 + // 包括:最后活跃时间、消息计数、用户信息等 + // 用于会话管理、超时检测、数据统计等 + void runtime.channel.session.recordSessionMetaFromInbound({ + storePath, // 会话存储路径 + sessionKey: ctx.SessionKey as string ?? route.sessionKey, // 会话键 + ctx, // 消息上下文 + }).catch((err: unknown) => { + console.log(`[wechat-access] 记录会话元数据失败: ${String(err)}`); + }); + + // ============================================ + // 4. 记录频道活动统计 + // ============================================ + // runtime.channel.activity.record 记录频道的活动统计 + // 用于监控、分析、计费等场景 + runtime.channel.activity.record({ + channel: "wechat-access", // 频道标识 + accountId: "default", // 账号 ID + direction: "inbound", // 方向:inbound=入站(用户发送),outbound=出站(Bot 回复) + }); + + // ============================================ + // 5. 调用 OpenClaw Agent 处理消息 + // ============================================ + try { + let responseText: string | null = null; + + // 获取响应前缀配置(例如:是否显示"正在思考..."等提示) + // runtime.channel.reply.resolveEffectiveMessagesConfig 解析消息配置 + const messagesConfig = runtime.channel.reply.resolveEffectiveMessagesConfig(cfg, route.agentId); + + console.log("[wechat-access] 开始调用 Agent..."); + + // ============================================ + // runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher + // 这是 OpenClaw 的核心消息分发方法 + // ============================================ + // 功能: + // 1. 将消息发送给 Agent 进行处理 + // 2. 通过 deliver 回调接收 Agent 的回复 + // 3. 支持流式回复(block)和最终回复(final) + // 4. 支持工具调用(tool)的结果 + // + // 参数说明: + // - ctx: 消息上下文(包含用户消息、会话信息等) + // - cfg: 全局配置 + // - dispatcherOptions: 分发器选项 + // - responsePrefix: 响应前缀(例如:"正在思考...") + // - deliver: 回调函数,接收 Agent 的回复 + // - onError: 错误处理回调 + // - replyOptions: 回复选项(可选) + // + // deliver 回调的 info.kind 类型: + // - "block": 流式分块回复(增量文本) + // - "tool": 工具调用结果(如 read_file、write 等) + // - "final": 最终完整回复 + const { queuedFinal } = await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({ + ctx, + cfg, + dispatcherOptions: { + responsePrefix: messagesConfig.responsePrefix, + deliver: async ( + payload: { text?: string; mediaUrl?: string; mediaUrls?: string[]; isError?: boolean; channelData?: unknown }, + info: { kind: string } + ) => { + console.log(`[wechat-access] Agent ${info.kind} 回复:`, payload, info); + + if (info.kind === "tool") { + // ============================================ + // 工具调用结果 + // ============================================ + // Agent 调用工具(如 write、read_file 等)后的结果 + // 通常不需要直接返回给用户,仅记录日志 + console.log("[wechat-access] 工具调用结果:", payload); + } else if (info.kind === "block") { + // ============================================ + // 流式分块回复 + // ============================================ + // Agent 生成的增量文本(流式输出) + // 累积到 responseText 中 + if (payload.text) { + // 检测安全审核拦截标记:替换为通用安全提示,不暴露具体拦截原因 + if (payload.text.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access] block 回复中检测到安全审核拦截标记,替换为安全提示"); + responseText = SECURITY_BLOCK_USER_MESSAGE; + } else { + responseText = payload.text; + } + } + } else if (info.kind === "final") { + // ============================================ + // 最终完整回复 + // ============================================ + // Agent 生成的完整回复文本 + // 这是最终返回给用户的内容 + if (payload.text) { + // 检测安全审核拦截标记:替换为通用安全提示 + if (payload.text.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access] final 回复中检测到安全审核拦截标记,替换为安全提示"); + responseText = SECURITY_BLOCK_USER_MESSAGE; + } else { + responseText = payload.text; + } + } + console.log("[wechat-access] 最终回复:", payload); + } + + // 记录出站活动统计(Bot 回复) + runtime.channel.activity.record({ + channel: "wechat-access", + accountId: "default", + direction: "outbound", // 出站:Bot 发送给用户 + }); + }, + onError: (err: unknown, info: { kind: string }) => { + console.error(`[wechat-access] ${info.kind} 回复失败:`, err); + }, + }, + replyOptions: {}, + }); + + if (!queuedFinal) { + console.log("[wechat-access] Agent 没有生成回复"); + } + + // ============================================ + // 后置处理:将结果发送到回调服务 + // ============================================ + const callbackPayload: CallbackPayload = { + userId, + messageId, + messageType, + userMessage: content, + aiReply: responseText, + timestamp, + sessionKey: route.sessionKey, + success: true, + }; + + // 异步发送,不阻塞返回 + // void sendToCallbackService(callbackPayload); + + return responseText; + } catch (err) { + console.error("[wechat-access] 消息分发失败:", err); + + // 即使失败也发送回调(带错误信息) + const callbackPayload: CallbackPayload = { + userId, + messageId, + messageType, + userMessage: content, + aiReply: null, + timestamp, + sessionKey: route.sessionKey, + success: false, + error: err instanceof Error ? err.message : String(err), + }; + + // void sendToCallbackService(callbackPayload); + + return null; + } +}; + +/** + * 处理消息并流式返回结果(SSE 模式) + * @param message - 微信服务号的原始消息对象 + * @param onChunk - 流式数据块回调函数,每次有新数据时调用 + * @returns Promise 异步执行,通过 onChunk 回调返回数据 + * @description + * 流式处理流程: + * 1. 提取消息基本信息 + * 2. 构建消息上下文 + * 3. 记录会话元数据和频道活动 + * 4. 订阅全局 Agent 事件(onAgentEvent) + * 5. 调用 Agent 处理消息 + * 6. 通过 onChunk 回调实时推送数据 + * 7. 发送完成信号 + * + * 流式数据类型: + * - block: 流式文本块(增量文本) + * - tool_start: 工具开始执行 + * - tool_update: 工具执行中间状态 + * - tool_result: 工具执行完成 + * - final: 最终完整回复 + * - error: 错误信息 + * - done: 流式传输完成 + * + * 内部关键方法: + * - runtime.events.onAgentEvent: 订阅 Agent 事件(assistant/tool/lifecycle 流) + * - runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher: 分发消息到 Agent + */ +export const handleMessageStream = async ( + message: FuwuhaoMessage, + onChunk: StreamCallback +): Promise => { + const runtime = getWecomRuntime(); + const cfg = runtime.config.loadConfig(); + + // ============================================ + // 1. 提取消息基本信息 + // ============================================ + const content = message.Content || message.text?.content || ""; + const userId = message.FromUserName || message.userid || "unknown"; + const messageId = String(message.MsgId || message.msgid || Date.now()); + const messageType = message.msgtype || "text"; + + console.log("[wechat-access] 流式处理消息:", { + 类型: messageType, + 消息ID: messageId, + 内容: content, + 用户ID: userId, + }); + + // ============================================ + // 2. 构建消息上下文 + // ============================================ + const { ctx, route, storePath } = buildMessageContext(message); + + // ============================================ + // 3. 记录会话元数据 + // ============================================ + void runtime.channel.session.recordSessionMetaFromInbound({ + storePath, + sessionKey: ctx.SessionKey as string ?? route.sessionKey, + ctx, + }).catch((err: unknown) => { + console.log(`[wechat-access] 记录会话元数据失败: ${String(err)}`); + }); + + // ============================================ + // 4. 记录频道活动统计 + // ============================================ + runtime.channel.activity.record({ + channel: "wechat-access", + accountId: "default", + direction: "inbound", + }); + + // ============================================ + // 5. 订阅全局 Agent 事件 + // ============================================ + // runtime.events.onAgentEvent 订阅 Agent 运行时产生的所有事件 + // 用于捕获流式文本、工具调用、生命周期等信息 + // + // 事件流类型: + // - assistant: 助手流(流式文本输出) + // - tool: 工具流(工具调用的各个阶段) + // - lifecycle: 生命周期流(start/end/error 等) + console.log("[wechat-access] 注册 onAgentEvent 监听器..."); + let lastEmittedText = ""; // 用于去重,只发送增量文本 + +const unsubscribeAgentEvents = onAgentEvent((evt: AgentEventPayload) => { + // 记录所有事件(调试用) + console.log(`[wechat-access] 收到 AgentEvent: stream=${evt.stream}, runId=${evt.runId}`); + + const data = evt.data as Record; + + // ============================================ + // 处理流式文本(assistant 流) + // ============================================ + // evt.stream === "assistant" 表示这是助手的文本输出流 + // data.delta: 增量文本(新增的部分) + // data.text: 累积文本(从开始到现在的完整文本) + if (evt.stream === "assistant") { + const delta = data.delta as string | undefined; + const text = data.text as string | undefined; + + // 优先使用 delta(增量文本),如果没有则计算增量 + let textToSend = delta; + if (!textToSend && text && text !== lastEmittedText) { + // 计算增量:新文本 - 已发送文本 + textToSend = text.slice(lastEmittedText.length); + lastEmittedText = text; + } else if (delta) { + lastEmittedText += delta; + } + + // 检测安全审核拦截标记:流式文本中包含拦截标记时,停止继续推送 + if (textToSend && textToSend.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access] 流式文本中检测到安全审核拦截标记,停止推送"); + return; + } + if (lastEmittedText.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access] 累积文本中检测到安全审核拦截标记,停止推送"); + return; + } + + if (textToSend) { + const cleanedText = stripThinkingTags(textToSend); + if (!cleanedText) return; // 过滤后为空则跳过 + console.log(`[wechat-access] 流式文本:`, cleanedText.slice(0, 50) + (cleanedText.length > 50 ? "..." : "")); + // 通过 onChunk 回调发送增量文本 + onChunk({ + type: "block", + text: cleanedText, + timestamp: evt.ts, + }); + } + return; + } + + // ============================================ + // 处理工具调用事件(tool 流) + // ============================================ + // evt.stream === "tool" 表示这是工具调用流 + // data.phase: 工具调用的阶段(start/update/result) + // data.name: 工具名称(如 read_file、write 等) + // data.toolCallId: 工具调用 ID(用于关联同一次调用的多个事件) + if (evt.stream === "tool") { + const phase = data.phase as string | undefined; + const toolName = data.name as string | undefined; + const toolCallId = data.toolCallId as string | undefined; + + console.log(`[wechat-access] 工具事件 [${phase}]:`, toolName, toolCallId); + + if (phase === "start") { + // ============================================ + // 工具开始执行 + // ============================================ + // 发送工具开始事件,包含工具名称和参数 + onChunk({ + type: "tool_start", + toolName, + toolCallId, + toolArgs: data.args as Record | undefined, + toolMeta: data.meta as Record | undefined, + timestamp: evt.ts, + }); + } else if (phase === "update") { + // ============================================ + // 工具执行中间状态更新 + // ============================================ + // 某些工具(如长时间运行的任务)会发送中间状态 + onChunk({ + type: "tool_update", + toolName, + toolCallId, + text: data.text as string | undefined, + toolMeta: data.meta as Record | undefined, + timestamp: evt.ts, + }); + } else if (phase === "result") { + // ============================================ + // 工具执行完成 + // ============================================ + // 发送工具执行结果,包含返回值和是否出错 + onChunk({ + type: "tool_result", + toolName, + toolCallId, + text: data.result as string | undefined, + isError: data.isError as boolean | undefined, + toolMeta: data.meta as Record | undefined, + timestamp: evt.ts, + }); + } + return; + } + + // ============================================ + // 处理生命周期事件(lifecycle 流) + // ============================================ + // evt.stream === "lifecycle" 表示这是生命周期事件 + // data.phase: 生命周期阶段(start/end/error) + if (evt.stream === "lifecycle") { + const phase = data.phase as string | undefined; + console.log(`[wechat-access] 生命周期事件 [${phase}]`); + // 可以在这里处理 start/end/error 事件,例如: + // if (phase === "error") { + // onChunk({ type: "error", text: data.error as string, timestamp: evt.ts }); + // } + } + }); + + try { + // 获取响应前缀配置 + const messagesConfig = runtime.channel.reply.resolveEffectiveMessagesConfig(cfg, route.agentId); + + console.log("[wechat-access] 开始流式调用 Agent..."); + console.log("[wechat-access] ctx:", JSON.stringify(ctx)); + + const dispatchResult = await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({ + ctx, + cfg, + dispatcherOptions: { + responsePrefix: messagesConfig.responsePrefix, + deliver: async ( + payload: { text?: string; mediaUrl?: string; mediaUrls?: string[]; isError?: boolean; channelData?: unknown }, + info: { kind: string } + ) => { + console.log(`[wechat-access] 流式 ${info.kind} 回复:`, payload, info); + + if (info.kind === "tool") { + // 工具调用结果 + onChunk({ + type: "tool", + text: payload.text, + isError: payload.isError, + timestamp: Date.now(), + }); + } else if (info.kind === "block") { + // 流式分块回复 + // 检测安全审核拦截标记:替换为通用安全提示 + let blockText = payload.text ? stripThinkingTags(payload.text) : payload.text; + if (blockText && blockText.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access] 流式 block deliver 中检测到安全审核拦截标记,替换为安全提示"); + blockText = SECURITY_BLOCK_USER_MESSAGE; + } + onChunk({ + type: "block", + text: blockText, + timestamp: Date.now(), + }); + } else if (info.kind === "final") { + // 最终完整回复 + // 检测安全审核拦截标记:替换为通用安全提示 + let finalText = payload.text ? stripThinkingTags(payload.text) : payload.text; + if (finalText && finalText.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access] 流式 final deliver 中检测到安全审核拦截标记,替换为安全提示"); + finalText = SECURITY_BLOCK_USER_MESSAGE; + } + onChunk({ + type: "final", + text: finalText, + timestamp: Date.now(), + }); + } + + // 记录出站活动 + runtime.channel.activity.record({ + channel: "wechat-access", + accountId: "default", + direction: "outbound", + }); + }, + onError: (err: unknown, info: { kind: string }) => { + console.error(`[wechat-access] 流式 ${info.kind} 回复失败:`, err); + onChunk({ + type: "error", + text: err instanceof Error ? err.message : String(err), + timestamp: Date.now(), + }); + }, + }, + replyOptions: {}, + }); + + console.log("[wechat-access] dispatchReplyWithBufferedBlockDispatcher 完成, 结果:", dispatchResult); + + // 取消订阅 Agent 事件 + unsubscribeAgentEvents(); + + // 发送完成信号 + onChunk({ + type: "done", + timestamp: Date.now(), + }); + + } catch (err) { + // 确保在异常时也取消订阅 + unsubscribeAgentEvents(); + console.error("[wechat-access] 流式消息分发失败:", err); + onChunk({ + type: "error", + text: err instanceof Error ? err.message : String(err), + timestamp: Date.now(), + }); + } +}; diff --git a/http/types.ts b/http/types.ts new file mode 100644 index 0000000..212788e --- /dev/null +++ b/http/types.ts @@ -0,0 +1,148 @@ +// ============================================ +// Agent 事件类型 +// ============================================ +/** + * Agent 事件载荷 + * @description OpenClaw Agent 运行时产生的事件数据 + * @property runId - 运行 ID,标识一次完整的 Agent 执行 + * @property seq - 事件序列号,用于排序 + * @property stream - 事件流类型(assistant/tool/lifecycle) + * @property ts - 时间戳(毫秒) + * @property data - 事件数据,根据 stream 类型不同而不同 + * @property sessionKey - 会话键(可选) + */ +export type AgentEventPayload = { + runId: string; + seq: number; + stream: string; + ts: number; + data: Record; + sessionKey?: string; +}; + +// ============================================ +// 消息类型 +// ============================================ +/** + * 微信服务号消息格式 + * @description 兼容多种消息格式(加密/明文、不同字段命名) + * @property msgtype - 消息类型(text/image/voice 等) + * @property msgid - 消息 ID(小写) + * @property MsgId - 消息 ID(大写,微信标准格式) + * @property text - 文本消息对象(包含 content 字段) + * @property Content - 文本内容(直接字段) + * @property chattype - 聊天类型 + * @property chatid - 聊天 ID + * @property userid - 用户 ID(小写) + * @property FromUserName - 发送者 OpenID(微信标准格式) + * @property ToUserName - 接收者 ID(服务号原始 ID) + * @property CreateTime - 消息创建时间(Unix 时间戳,秒) + */ +export interface FuwuhaoMessage { + msgtype?: string; + msgid?: string; + MsgId?: string; + text?: { + content?: string; + }; + Content?: string; + chattype?: string; + chatid?: string; + userid?: string; + FromUserName?: string; + ToUserName?: string; + CreateTime?: number; +} + +// ============================================ +// 账号配置类型 +// ============================================ +/** + * 微信服务号账号配置 + * @description 用于消息加密解密和签名验证 + * @property token - 微信服务号配置的 Token(用于签名验证) + * @property encodingAESKey - 消息加密密钥(43位字符,Base64 编码) + * @property receiveId - 接收方 ID(服务号的原始 ID,用于解密验证) + */ +export interface SimpleAccount { + token: string; + encodingAESKey: string; + receiveId: string; +} + +// ============================================ +// 回调相关类型 +// ============================================ +/** + * 后置回调数据载荷 + * @description 发送到外部回调服务的数据格式 + * @property userId - 用户唯一标识(OpenID) + * @property messageId - 消息唯一标识 + * @property messageType - 消息类型(text/image/voice 等) + * @property userMessage - 用户发送的原始消息内容 + * @property aiReply - AI 生成的回复内容(如果失败则为 null) + * @property timestamp - 消息时间戳(毫秒) + * @property sessionKey - 会话键,用于关联上下文 + * @property success - 处理是否成功 + * @property error - 错误信息(仅在失败时存在) + */ +export interface CallbackPayload { + // 用户信息 + userId: string; + // 消息信息 + messageId: string; + messageType: string; + // 用户发送的原始内容 + userMessage: string; + // AI 回复的内容 + aiReply: string | null; + // 时间戳 + timestamp: number; + // 会话信息 + sessionKey: string; + // 是否成功 + success: boolean; + // 错误信息(如果有) + error?: string; +} + +// ============================================ +// 流式消息类型 +// ============================================ +/** + * 流式消息数据块 + * @description Server-Sent Events (SSE) 推送的数据格式 + * @property type - 数据块类型 + * - block: 流式文本块(增量文本) + * - tool: 工具调用结果 + * - tool_start: 工具开始执行 + * - tool_update: 工具执行中间状态 + * - tool_result: 工具执行完成 + * - final: 最终完整回复 + * - error: 错误信息 + * - done: 流式传输完成 + * @property text - 文本内容(适用于 block/final/error) + * @property toolName - 工具名称(适用于 tool_* 类型) + * @property toolCallId - 工具调用 ID(用于关联同一次调用) + * @property toolArgs - 工具调用参数(适用于 tool_start) + * @property toolMeta - 工具元数据(适用于 tool_* 类型) + * @property isError - 是否是错误(适用于 tool_result) + * @property timestamp - 时间戳(毫秒) + */ +export interface StreamChunk { + type: "block" | "tool" | "tool_start" | "tool_update" | "tool_result" | "final" | "error" | "done"; + text?: string; + toolName?: string; + toolCallId?: string; + toolArgs?: Record; + toolMeta?: Record; + isError?: boolean; + timestamp: number; +} + +/** + * 流式消息回调函数类型 + * @description 用于接收流式数据块的回调函数 + * @param chunk - 流式数据块 + */ +export type StreamCallback = (chunk: StreamChunk) => void; diff --git a/http/webhook.ts b/http/webhook.ts new file mode 100644 index 0000000..8c926f9 --- /dev/null +++ b/http/webhook.ts @@ -0,0 +1,278 @@ +import type { IncomingMessage, ServerResponse } from "node:http"; +import type { FuwuhaoMessage, SimpleAccount } from "./types.js"; +import { verifySignature, decryptMessage } from "./crypto-utils.js"; +import { parseQuery, readBody, isFuwuhaoWebhookPath } from "./http-utils.js"; +import { handleMessage, handleMessageStream } from "./message-handler.js"; + +// ============================================ +// 账号配置 +// ============================================ +// 微信服务号的账号配置信息 +// 生产环境应从环境变量或配置文件中读取 + +/** + * 模拟账号存储 + * @description + * 生产环境建议: + * 1. 从环境变量读取:process.env.FUWUHAO_TOKEN 等 + * 2. 从配置文件读取:config.json + * 3. 从数据库读取:支持多账号场景 + * 4. 使用密钥管理服务:如 AWS Secrets Manager + */ +const mockAccount: SimpleAccount = { + token: "your_token_here", // 微信服务号配置的 Token + encodingAESKey: "your_encoding_aes_key_here", // 消息加密密钥(43位字符) + receiveId: "your_receive_id_here" // 服务号的原始 ID +}; + +// ============================================ +// Webhook 处理器(主入口) +// ============================================ +/** + * 处理微信服务号的 Webhook 请求 + * @param req - Node.js HTTP 请求对象 + * @param res - Node.js HTTP 响应对象 + * @returns Promise 是否处理了此请求(true=已处理,false=交给其他处理器) + * @description + * 此函数是微信服务号集成的主入口,负责: + * 1. 路径匹配:检查是否是服务号 webhook 路径 + * 2. GET 请求:处理 URL 验证(微信服务器验证) + * 3. POST 请求:处理用户消息 + * - 支持加密消息(验证签名 + 解密) + * - 支持明文消息(测试用) + * - 支持同步返回和流式返回(SSE) + * + * 请求流程: + * - GET /wechat-access?signature=xxx×tamp=xxx&nonce=xxx&echostr=xxx + * → 验证签名 → 解密 echostr → 返回明文 + * - POST /wechat-access (同步) + * → 验证签名 → 解密消息 → 调用 Agent → 返回 JSON + * - POST /wechat-access?stream=true (流式) + * → 验证签名 → 解密消息 → 调用 Agent → 返回 SSE 流 + */ +export const handleSimpleWecomWebhook = async ( + req: IncomingMessage, + res: ServerResponse +): Promise => { + // ============================================ + // 1. 路径匹配检查 + // ============================================ + // 检查请求路径是否匹配服务号 webhook 路径 + // 支持:/wechat-access、/wechat-access/webhook、/wechat-access/* + if (!isFuwuhaoWebhookPath(req.url || "")) { + return false; // 不是我们的路径,交给其他处理器 + } + + console.log(`[wechat-access] 收到请求: ${req.method} ${req.url}`); + + try { + // ============================================ + // 2. 解析查询参数 + // ============================================ + // 微信服务器会在 URL 中附加验证参数 + const query = parseQuery(req); + const timestamp = query.get("timestamp") || ""; // 时间戳 + const nonce = query.get("nonce") || ""; // 随机数 + const signature = query.get("msg_signature") || query.get("signature") || ""; // 签名 + + // ============================================ + // 3. 处理 GET 请求 - URL 验证 + // ============================================ + // 微信服务器在配置 webhook 时会发送 GET 请求验证 URL + // 请求格式:GET /wechat-access?signature=xxx×tamp=xxx&nonce=xxx&echostr=xxx + if (req.method === "GET") { + const echostr = query.get("echostr") || ""; + + // 验证签名(确保请求来自微信服务器) + const isValid = verifySignature({ + token: mockAccount.token, + timestamp, + nonce, + encrypt: echostr, + signature + }); + + if (!isValid) { + res.statusCode = 401; + res.setHeader("Content-Type", "text/plain; charset=utf-8"); + res.end("签名验证失败"); + return true; + } + + // 解密 echostr 并返回(微信服务器会验证返回值) + try { + const decrypted = decryptMessage({ + encodingAESKey: mockAccount.encodingAESKey, + receiveId: mockAccount.receiveId, + encrypt: echostr + }); + + res.statusCode = 200; + res.setHeader("Content-Type", "text/plain; charset=utf-8"); + res.end(decrypted); + return true; + } catch { + res.statusCode = 400; + res.setHeader("Content-Type", "text/plain; charset=utf-8"); + res.end("解密失败"); + return true; + } + } + + // ============================================ + // 4. 处理 POST 请求 - 用户消息 + // ============================================ + // 微信服务器会将用户发送的消息通过 POST 请求转发过来 + // 请求格式:POST /wechat-access?signature=xxx×tamp=xxx&nonce=xxx + // 请求体:加密的 JSON 或 XML 格式消息 + if (req.method === "POST") { + // 读取请求体 + const body = await readBody(req); + + let message: FuwuhaoMessage; + + // ============================================ + // 4.1 解析和解密消息 + // ============================================ + // 尝试解析 JSON 格式 + try { + const data = JSON.parse(body); + const encrypt = data.encrypt || data.Encrypt || ""; + + if (encrypt) { + // ============================================ + // 加密消息处理流程 + // ============================================ + // 1. 验证签名(确保消息来自微信服务器) + const isValid = verifySignature({ + token: mockAccount.token, + timestamp, + nonce, + encrypt, + signature + }); + + if (!isValid) { + res.statusCode = 401; + res.setHeader("Content-Type", "text/plain; charset=utf-8"); + res.end("签名验证失败"); + return true; + } + + // 2. 解密消息 + const decrypted = decryptMessage({ + encodingAESKey: mockAccount.encodingAESKey, + receiveId: mockAccount.receiveId, + encrypt + }); + message = JSON.parse(decrypted); + } else { + // ============================================ + // 明文消息(用于测试) + // ============================================ + // 直接使用 JSON 数据,无需解密 + message = data; + } + } catch { + // ============================================ + // XML 格式处理(简化版) + // ============================================ + // 可能是 XML 格式,简单处理 + console.log("[wechat-access] 收到非JSON格式数据,尝试简单解析"); + message = { + msgtype: "text", + Content: body, + FromUserName: "unknown", + MsgId: `${Date.now()}` + }; + } + + // ============================================ + // 4.2 检查是否请求流式返回(SSE) + // ============================================ + // 客户端可以通过以下方式请求流式返回: + // 1. Accept: text/event-stream header + // 2. ?stream=true 查询参数 + // 3. ?stream=1 查询参数 + const acceptHeader = req.headers.accept || ""; + const wantsStream = acceptHeader.includes("text/event-stream") || + query.get("stream") === "true" || + query.get("stream") === "1"; + console.log('adam-sssss-markoint===wantsStreamwantsStreamwantsStream', wantsStream) + if (wantsStream) { + // ============================================ + // 流式返回模式(Server-Sent Events) + // ============================================ + // SSE 是一种服务器向客户端推送实时数据的技术 + // 适用于:实时显示 AI 生成过程、工具调用状态等 + console.log("[wechat-access] 使用流式返回模式 (SSE)"); + + // 设置 SSE 响应头 + res.statusCode = 200; + res.setHeader("Content-Type", "text/event-stream; charset=utf-8"); // SSE 标准格式 + res.setHeader("Cache-Control", "no-cache, no-transform"); // 禁用缓存 + res.setHeader("Connection", "keep-alive"); // 保持连接 + res.setHeader("X-Accel-Buffering", "no"); // 禁用 nginx 缓冲 + res.setHeader("Access-Control-Allow-Origin", "*"); // 允许跨域 + res.flushHeaders(); // 立即发送 headers,建立 SSE 连接 + + // 发送初始连接确认事件 + const connectedEvent = `data: ${JSON.stringify({ type: "connected", timestamp: Date.now() })}\n\n`; + console.log("[wechat-access] SSE 发送连接确认:", connectedEvent.trim()); + res.write(connectedEvent); + + try { + // 调用流式消息处理器 + // handleMessageStream 会通过回调函数实时推送数据 + await handleMessageStream(message, (chunk) => { + // SSE 数据格式:data: {JSON}\n\n + const sseData = `data: ${JSON.stringify(chunk)}\n\n`; + console.log("[wechat-access] SSE 发送数据:", chunk.type, chunk.text?.slice(0, 50)); + res.write(sseData); + + // 如果是完成或错误,关闭连接 + if (chunk.type === "done" || chunk.type === "error") { + console.log("[wechat-access] SSE 连接关闭:", chunk.type); + res.end(); + } + }); + } catch (streamErr) { + // 流式处理异常,发送错误事件 + console.error("[wechat-access] SSE 流式处理异常:", streamErr); + const errorData = `data: ${JSON.stringify({ type: "error", text: String(streamErr), timestamp: Date.now() })}\n\n`; + res.write(errorData); + res.end(); + } + + return true; + } + + // ============================================ + // 4.3 普通同步返回模式 + // ============================================ + // 等待 Agent 处理完成后一次性返回结果 + // 适用于:简单问答、不需要实时反馈的场景 + const reply = await handleMessage(message); + + res.statusCode = 200; + res.setHeader("Content-Type", "application/json; charset=utf-8"); + res.end(JSON.stringify({ + success: true, + reply: reply || "消息已接收,正在处理中..." + })); + return true; + } + + return false; + } catch (error) { + // ============================================ + // 5. 异常处理 + // ============================================ + // 捕获所有未处理的异常,返回 500 错误 + console.error("[wechat-access] Webhook 处理异常:", error); + res.statusCode = 500; + res.setHeader("Content-Type", "text/plain; charset=utf-8"); + res.end("服务器内部错误"); + return true; + } +}; \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..c948c9d --- /dev/null +++ b/index.ts @@ -0,0 +1,236 @@ +import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import { WechatAccessWebSocketClient, handlePrompt, handleCancel } from "./websocket/index.js"; +// import { handleSimpleWecomWebhook } from "./http/webhook.js"; +import { setWecomRuntime } from "./common/runtime.js"; +import { performLogin, loadState, getDeviceGuid, getEnvironment } from "./auth/index.js"; + +// 类型定义 +type NormalizedChatType = "direct" | "group" | "channel"; + +// WebSocket 客户端实例(按 accountId 存储) +const wsClients = new Map(); + +// 渠道元数据 +const meta = { + id: "wechat-access", + label: "腾讯通路", + /** 选择时的显示文本 */ + selectionLabel: "腾讯通路", + detailLabel: "腾讯通路", + /** 文档路径 */ + docsPath: "/channels/wechat-access", + docsLabel: "wechat-access", + /** 简介 */ + blurb: "通用通路", + /** 图标 */ + systemImage: "message.fill", + /** 排序权重 */ + order: 85, +}; + +// 渠道插件 +const tencentAccessPlugin = { + id: "wechat-access", + meta, + + // 能力声明 + capabilities: { + chatTypes: ["direct"] as NormalizedChatType[], + reactions: false, + threads: false, + media: true, + nativeCommands: false, + blockStreaming: false, + }, + + // 热重载:token 或 wsUrl 变更时触发 gateway 重启 + reload: { + configPrefixes: ["channels.wechat-access.token", "channels.wechat-access.wsUrl"], + }, + + // 配置适配器(必需) + config: { + listAccountIds: (cfg: any) => { + const accounts = cfg.channels?.["wechat-access"]?.accounts; + if (accounts && typeof accounts === "object") { + return Object.keys(accounts); + } + // 没有配置账号时,返回默认账号 + return ["default"]; + }, + resolveAccount: (cfg: any, accountId: string) => { + const accounts = cfg.channels?.["wechat-access"]?.accounts; + const account = accounts?.[accountId ?? "default"]; + return account ?? { accountId: accountId ?? "default" }; + }, + }, + + // 出站适配器(必需) + outbound: { + deliveryMode: "direct" as const, + sendText: async () => ({ ok: true }), + }, + + // 状态适配器:上报 WebSocket 连接状态 + status: { + buildAccountSnapshot: ({ accountId }: { accountId?: string; cfg: any; runtime?: any }) => { + const client = wsClients.get(accountId ?? "default"); + const running = client?.getState() === "connected"; + return { running }; + }, + }, + + // Gateway 适配器:按账号启动/停止 WebSocket 连接 + gateway: { + startAccount: async (ctx: any) => { + const { cfg, accountId, abortSignal, log } = ctx; + + const tencentAccessConfig = cfg?.channels?.["wechat-access"]; + let token = tencentAccessConfig?.token ? String(tencentAccessConfig.token) : ""; + const configWsUrl = tencentAccessConfig?.wsUrl ? String(tencentAccessConfig.wsUrl) : ""; + const bypassInvite = tencentAccessConfig?.bypassInvite === true; + const authStatePath = tencentAccessConfig?.authStatePath + ? String(tencentAccessConfig.authStatePath) + : undefined; + const envName: string = tencentAccessConfig?.environment + ? String(tencentAccessConfig.environment) + : "production"; + const gatewayPort = cfg?.gateway?.port ? String(cfg.gateway.port) : "unknown"; + + const env = getEnvironment(envName); + const guid = getDeviceGuid(); + const wsUrl = configWsUrl || env.wechatWsUrl; + + // 启动诊断日志 + log?.info(`[wechat-access] 启动账号 ${accountId}`, { + platform: process.platform, + nodeVersion: process.version, + hasToken: !!token, + hasUrl: !!wsUrl, + url: wsUrl || "(未配置)", + tokenPrefix: token ? token.substring(0, 6) + "..." : "(未配置)", + }); + + // Token 获取策略:配置 > 已保存的登录态 > 交互式扫码登录 + if (!token) { + const savedState = loadState(authStatePath); + if (savedState?.channelToken) { + token = savedState.channelToken; + log?.info(`[wechat-access] 使用已保存的 token: ${token.substring(0, 6)}...`); + } else { + log?.info(`[wechat-access] 未找到 token,启动微信扫码登录...`); + try { + const credentials = await performLogin({ + guid, + env, + bypassInvite, + authStatePath, + log, + }); + token = credentials.channelToken; + } catch (err) { + log?.error(`[wechat-access] 登录失败: ${err}`); + return; + } + } + } + + if (!token) { + log?.warn(`[wechat-access] token 为空,跳过 WebSocket 连接`); + return; + } + + const wsConfig = { + url: wsUrl, + token, + guid, + userId: "", + gatewayPort, + reconnectInterval: 3000, + maxReconnectAttempts: 10, + heartbeatInterval: 20000, + }; + + const client = new WechatAccessWebSocketClient(wsConfig, { + onConnected: () => { + log?.info(`[wechat-access] WebSocket 连接成功`); + ctx.setStatus({ running: true }); + }, + onDisconnected: (reason?: string) => { + log?.warn(`[wechat-access] WebSocket 连接断开: ${reason}`); + ctx.setStatus({ running: false }); + }, + onPrompt: (message: any) => { + void handlePrompt(message, client).catch((err: Error) => { + log?.error(`[wechat-access] 处理 prompt 失败: ${err.message}`); + }); + }, + onCancel: (message: any) => { + handleCancel(message, client); + }, + onError: (error: Error) => { + log?.error(`[wechat-access] WebSocket 错误: ${error.message}`); + }, + }); + + wsClients.set(accountId, client); + client.start(); + + // 等待框架发出停止信号 + await new Promise((resolve) => { + abortSignal.addEventListener("abort", () => { + log?.info(`[wechat-access] 停止账号 ${accountId}`); + // 始终停止当前闭包捕获的 client,避免多次 startAccount 时 + // wsClients 被新 client 覆盖后,旧 client 的 stop() 永远不被调用,导致无限重连 + client.stop(); + // 仅当 wsClients 中存的还是当前 client 时才删除,避免误删新 client + if (wsClients.get(accountId) === client) { + wsClients.delete(accountId); + ctx.setStatus({ running: false }); + } + resolve(); + }); + }); + }, + + stopAccount: async (ctx: any) => { + const { accountId, log } = ctx; + log?.info(`[wechat-access] stopAccount 钩子触发,停止账号 ${accountId}`); + const client = wsClients.get(accountId); + if (client) { + client.stop(); + wsClients.delete(accountId); + ctx.setStatus({ running: false }); + log?.info(`[wechat-access] 账号 ${accountId} 已停止`); + } else { + log?.warn(`[wechat-access] stopAccount: 未找到账号 ${accountId} 的客户端`); + } + }, + }, +}; + +const index = { + id: "wechat-access", + name: "通用通路插件", + description: "腾讯通用通路插件", + configSchema: emptyPluginConfigSchema(), + + /** + * 插件注册入口点 + */ + register(api: OpenClawPluginApi) { + // 1. 设置运行时环境 + setWecomRuntime(api.runtime); + + // 2. 注册渠道插件 + api.registerChannel({ plugin: tencentAccessPlugin as any }); + + // 3. 注册 HTTP 处理器(如需要) + // api.registerHttpHandler(handleSimpleWecomWebhook); + + console.log("[wechat-access] 腾讯通路插件已注册"); + }, +}; + +export default index; \ No newline at end of file diff --git a/openclaw.plugin.json b/openclaw.plugin.json new file mode 100644 index 0000000..56c71d1 --- /dev/null +++ b/openclaw.plugin.json @@ -0,0 +1,38 @@ +{ + "id": "wechat-access", + "channels": ["wechat-access"], + "configSchema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "是否启用服务号渠道" + }, + "token": { + "type": "string", + "description": "WebSocket 连接 token(手动配置时使用)" + }, + "wsUrl": { + "type": "string", + "description": "WebSocket 网关地址" + }, + "bypassInvite": { + "type": "boolean", + "description": "跳过邀请码验证" + }, + "authStatePath": { + "type": "string", + "description": "自定义 token 持久化路径" + }, + "environment": { + "type": "string", + "enum": ["production", "test"], + "description": "API 环境(production / test)" + }, + "accounts": { + "type": "object", + "description": "多账号配置" + } + } + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..77625c7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,10202 @@ +{ + "name": "wechat-access", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "wechat-access", + "version": "1.0.0", + "dependencies": { + "fast-xml-parser": "^5.4.1", + "qrcode-terminal": "^0.12.0", + "undici": "^7.20.0", + "ws": "^8.18.0", + "zod": "^4.3.6" + }, + "peerDependencies": { + "openclaw": ">=2026.1.26" + } + }, + "../..": { + "version": "2026.2.1", + "extraneous": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@agentclientprotocol/sdk": "0.13.1", + "@aws-sdk/client-bedrock": "^3.981.0", + "@buape/carbon": "0.14.0", + "@clack/prompts": "^1.0.0", + "@grammyjs/runner": "^2.0.3", + "@grammyjs/transformer-throttler": "^1.2.1", + "@homebridge/ciao": "^1.3.4", + "@line/bot-sdk": "^10.6.0", + "@lydell/node-pty": "1.2.0-beta.3", + "@mariozechner/pi-agent-core": "0.51.1", + "@mariozechner/pi-ai": "0.51.1", + "@mariozechner/pi-coding-agent": "0.51.1", + "@mariozechner/pi-tui": "0.51.1", + "@mozilla/readability": "^0.6.0", + "@sinclair/typebox": "0.34.48", + "@slack/bolt": "^4.6.0", + "@slack/web-api": "^7.13.0", + "@whiskeysockets/baileys": "7.0.0-rc.9", + "ajv": "^8.17.1", + "chalk": "^5.6.2", + "chokidar": "^5.0.0", + "cli-highlight": "^2.1.11", + "commander": "^14.0.3", + "croner": "^10.0.1", + "discord-api-types": "^0.38.38", + "dotenv": "^17.2.3", + "express": "^5.2.1", + "file-type": "^21.3.0", + "grammy": "^1.39.3", + "hono": "4.11.7", + "jiti": "^2.6.1", + "json5": "^2.2.3", + "jszip": "^3.10.1", + "linkedom": "^0.18.12", + "long": "^5.3.2", + "markdown-it": "^14.1.0", + "node-edge-tts": "^1.2.9", + "osc-progress": "^0.3.0", + "pdfjs-dist": "^5.4.624", + "playwright-core": "1.58.1", + "proper-lockfile": "^4.1.2", + "qrcode-terminal": "^0.12.0", + "sharp": "^0.34.5", + "signal-utils": "^0.21.1", + "sqlite-vec": "0.1.7-alpha.2", + "tar": "7.5.7", + "tslog": "^4.10.2", + "undici": "^7.20.0", + "ws": "^8.19.0", + "yaml": "^2.8.2", + "zod": "^4.3.6" + }, + "bin": { + "openclaw": "openclaw.mjs" + }, + "devDependencies": { + "@grammyjs/types": "^3.23.0", + "@lit-labs/signals": "^0.2.0", + "@lit/context": "^1.1.6", + "@types/express": "^5.0.6", + "@types/markdown-it": "^14.1.2", + "@types/node": "^25.2.0", + "@types/proper-lockfile": "^4.1.4", + "@types/qrcode-terminal": "^0.12.2", + "@types/ws": "^8.18.1", + "@typescript/native-preview": "7.0.0-dev.20260202.1", + "@vitest/coverage-v8": "^4.0.18", + "lit": "^3.3.2", + "ollama": "^0.6.3", + "oxfmt": "0.28.0", + "oxlint": "^1.43.0", + "oxlint-tsgolint": "^0.11.4", + "rolldown": "1.0.0-rc.2", + "tsx": "^4.21.0", + "typescript": "^5.9.3", + "vitest": "^4.0.18" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "@napi-rs/canvas": "^0.1.89", + "node-llama-cpp": "3.15.1" + } + }, + "node_modules/@agentclientprotocol/sdk": { + "version": "0.15.0", + "resolved": "https://registry.npmmirror.com/@agentclientprotocol/sdk/-/sdk-0.15.0.tgz", + "integrity": "sha512-TH4utu23Ix8ec34srBHmDD4p3HI0cYleS1jN9lghRczPfhFlMBNrQgZWeBBe12DWy27L11eIrtciY2MXFSEiDg==", + "license": "Apache-2.0", + "peer": true, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.73.0", + "resolved": "https://registry.npmmirror.com/@anthropic-ai/sdk/-/sdk-0.73.0.tgz", + "integrity": "sha512-URURVzhxXGJDGUGFunIOtBlSl7KWvZiAAKY/ttTkZAkXT9bTPqdk2eK0b8qqSxXpikh3QKPnPYpiyX98zf5ebw==", + "license": "MIT", + "peer": true, + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock": { + "version": "3.1004.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/client-bedrock/-/client-bedrock-3.1004.0.tgz", + "integrity": "sha512-JbfZSV85IL+43S7rPBmeMbvoOYXs1wmrfbEpHkDBjkvbukRQWtoetiPAXNSKDfFq1qVsoq8sWPdoerDQwlUO8w==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/credential-provider-node": "^3.972.18", + "@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.19", + "@aws-sdk/region-config-resolver": "^3.972.7", + "@aws-sdk/token-providers": "3.1004.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.4", + "@smithy/config-resolver": "^4.4.10", + "@smithy/core": "^3.23.8", + "@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.22", + "@smithy/middleware-retry": "^4.4.39", + "@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.2", + "@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.38", + "@smithy/util-defaults-mode-node": "^4.2.41", + "@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.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime": { + "version": "3.1004.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1004.0.tgz", + "integrity": "sha512-t8cl+bPLlHZQD2Sw1a4hSLUybqJZU71+m8znkyeU8CHntFqEp2mMbuLKdHKaAYQ1fAApXMsvzenCAkDzNeeJlw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/credential-provider-node": "^3.972.18", + "@aws-sdk/eventstream-handler-node": "^3.972.10", + "@aws-sdk/middleware-eventstream": "^3.972.7", + "@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.19", + "@aws-sdk/middleware-websocket": "^3.972.12", + "@aws-sdk/region-config-resolver": "^3.972.7", + "@aws-sdk/token-providers": "3.1004.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.4", + "@smithy/config-resolver": "^4.4.10", + "@smithy/core": "^3.23.8", + "@smithy/eventstream-serde-browser": "^4.2.11", + "@smithy/eventstream-serde-config-resolver": "^4.3.11", + "@smithy/eventstream-serde-node": "^4.2.11", + "@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.22", + "@smithy/middleware-retry": "^4.4.39", + "@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.2", + "@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.38", + "@smithy/util-defaults-mode-node": "^4.2.41", + "@smithy/util-endpoints": "^3.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-retry": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.973.18", + "resolved": "https://registry.npmmirror.com/@aws-sdk/core/-/core-3.973.18.tgz", + "integrity": "sha512-GUIlegfcK2LO1J2Y98sCJy63rQSiLiDOgVw7HiHPRqfI2vb3XozTVqemwO0VSGXp54ngCnAQz0Lf0YPCBINNxA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/xml-builder": "^3.972.10", + "@smithy/core": "^3.23.8", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/smithy-client": "^4.12.2", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.16", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.16.tgz", + "integrity": "sha512-HrdtnadvTGAQUr18sPzGlE5El3ICphnH6SU7UQOMOWFgRKbTRNN8msTxM4emzguUso9CzaHU2xy5ctSrmK5YNA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.18", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.18.tgz", + "integrity": "sha512-NyB6smuZAixND5jZumkpkunQ0voc4Mwgkd+SZ6cvAzIB7gK8HV8Zd4rS8Kn5MmoGgusyNfVGG+RLoYc4yFiw+A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/types": "^3.973.5", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/smithy-client": "^4.12.2", + "@smithy/types": "^4.13.0", + "@smithy/util-stream": "^4.5.17", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.17", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.17.tgz", + "integrity": "sha512-dFqh7nfX43B8dO1aPQHOcjC0SnCJ83H3F+1LoCh3X1P7E7N09I+0/taID0asU6GCddfDExqnEvQtDdkuMe5tKQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/credential-provider-env": "^3.972.16", + "@aws-sdk/credential-provider-http": "^3.972.18", + "@aws-sdk/credential-provider-login": "^3.972.17", + "@aws-sdk/credential-provider-process": "^3.972.16", + "@aws-sdk/credential-provider-sso": "^3.972.17", + "@aws-sdk/credential-provider-web-identity": "^3.972.17", + "@aws-sdk/nested-clients": "^3.996.7", + "@aws-sdk/types": "^3.973.5", + "@smithy/credential-provider-imds": "^4.2.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.17", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.17.tgz", + "integrity": "sha512-gf2E5b7LpKb+JX2oQsRIDxdRZjBFZt2olCGlWCdb3vBERbXIPgm2t1R5mEnwd4j0UEO/Tbg5zN2KJbHXttJqwA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/nested-clients": "^3.996.7", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.18", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.18.tgz", + "integrity": "sha512-ZDJa2gd1xiPg/nBDGhUlat02O8obaDEnICBAVS8qieZ0+nDfaB0Z3ec6gjZj27OqFTjnB/Q5a0GwQwb7rMVViw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.16", + "@aws-sdk/credential-provider-http": "^3.972.18", + "@aws-sdk/credential-provider-ini": "^3.972.17", + "@aws-sdk/credential-provider-process": "^3.972.16", + "@aws-sdk/credential-provider-sso": "^3.972.17", + "@aws-sdk/credential-provider-web-identity": "^3.972.17", + "@aws-sdk/types": "^3.973.5", + "@smithy/credential-provider-imds": "^4.2.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.16", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.16.tgz", + "integrity": "sha512-n89ibATwnLEg0ZdZmUds5bq8AfBAdoYEDpqP3uzPLaRuGelsKlIvCYSNNvfgGLi8NaHPNNhs1HjJZYbqkW9b+g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@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.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.17", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.17.tgz", + "integrity": "sha512-wGtte+48xnhnhHMl/MsxzacBPs5A+7JJedjiP452IkHY7vsbYKcvQBqFye8LwdTJVeHtBHv+JFeTscnwepoWGg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/nested-clients": "^3.996.7", + "@aws-sdk/token-providers": "3.1004.0", + "@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.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.17", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.17.tgz", + "integrity": "sha512-8aiVJh6fTdl8gcyL+sVNcNwTtWpmoFa1Sh7xlj6Z7L/cZ/tYMEBHq44wTYG8Kt0z/PpGNopD89nbj3FHl9QmTA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/nested-clients": "^3.996.7", + "@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.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/eventstream-handler-node": { + "version": "3.972.10", + "resolved": "https://registry.npmmirror.com/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.10.tgz", + "integrity": "sha512-g2Z9s6Y4iNh0wICaEqutgYgt/Pmhv5Ev9G3eKGFe2w9VuZDhc76vYdop6I5OocmpHV79d4TuLG+JWg5rQIVDVA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/eventstream-codec": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-eventstream": { + "version": "3.972.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.7.tgz", + "integrity": "sha512-VWndapHYCfwLgPpCb/xwlMKG4imhFzKJzZcKOEioGn7OHY+6gdr0K7oqy1HZgbLa3ACznZ9fku+DzmAi8fUC0g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.972.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.7.tgz", + "integrity": "sha512-aHQZgztBFEpDU1BB00VWCIIm85JjGjQW1OG9+98BdmaOpguJvzmXBGbnAiYcciCd+IS4e9BEq664lhzGnWJHgQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.972.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-logger/-/middleware-logger-3.972.7.tgz", + "integrity": "sha512-LXhiWlWb26txCU1vcI9PneESSeRp/RYY/McuM4SpdrimQR5NgwaPb4VJCadVeuGWgh6QmqZ6rAKSoL1ob16W6w==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.972.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.7.tgz", + "integrity": "sha512-l2VQdcBcYLzIzykCHtXlbpiVCZ94/xniLIkAj0jpnpjY4xlgZx7f56Ypn+uV1y3gG0tNVytJqo3K9bfMFee7SQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.972.19", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.19.tgz", + "integrity": "sha512-Km90fcXt3W/iqujHzuM6IaDkYCj73gsYufcuWXApWdzoTy6KGk8fnchAjePMARU0xegIR3K4N3yIo1vy7OVe8A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-endpoints": "^3.996.4", + "@smithy/core": "^3.23.8", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-retry": "^4.2.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket": { + "version": "3.972.12", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.12.tgz", + "integrity": "sha512-iyPP6FVDKe/5wy5ojC0akpDFG1vX3FeCUU47JuwN8xfvT66xlEI8qUJZPtN55TJVFzzWZJpWL78eqUE31md08Q==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-format-url": "^3.972.7", + "@smithy/eventstream-codec": "^4.2.11", + "@smithy/eventstream-serde-browser": "^4.2.11", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.996.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/nested-clients/-/nested-clients-3.996.7.tgz", + "integrity": "sha512-MlGWA8uPaOs5AiTZ5JLM4uuWDm9EEAnm9cqwvqQIc6kEgel/8s1BaOWm9QgUcfc9K8qd7KkC3n43yDbeXOA2tg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.18", + "@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.19", + "@aws-sdk/region-config-resolver": "^3.972.7", + "@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.4", + "@smithy/config-resolver": "^4.4.10", + "@smithy/core": "^3.23.8", + "@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.22", + "@smithy/middleware-retry": "^4.4.39", + "@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.2", + "@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.38", + "@smithy/util-defaults-mode-node": "^4.2.41", + "@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.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.972.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.7.tgz", + "integrity": "sha512-/Ev/6AI8bvt4HAAptzSjThGUMjcWaX3GX8oERkB0F0F9x2dLSBdgFDiyrRz3i0u0ZFZFQ1b28is4QhyqXTUsVA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/config-resolver": "^4.4.10", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1004.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/token-providers/-/token-providers-3.1004.0.tgz", + "integrity": "sha512-j9BwZZId9sFp+4GPhf6KrwO8Tben2sXibZA8D1vv2I1zBdvkUHcBA2g4pkqIpTRalMTLC0NPkBPX0gERxfy/iA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/core": "^3.973.18", + "@aws-sdk/nested-clients": "^3.996.7", + "@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.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.973.5", + "resolved": "https://registry.npmmirror.com/@aws-sdk/types/-/types-3.973.5.tgz", + "integrity": "sha512-hl7BGwDCWsjH8NkZfx+HgS7H2LyM2lTMAI7ba9c8O0KqdBLTdNJivsHpqjg9rNlAlPyREb6DeDRXUl0s8uFdmQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.996.4", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-endpoints/-/util-endpoints-3.996.4.tgz", + "integrity": "sha512-Hek90FBmd4joCFj+Vc98KLJh73Zqj3s2W56gjAcTkrNLMDI5nIFkG9YpfcJiVI1YlE2Ne1uOQNe+IgQ/Vz2XRA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-endpoints": "^3.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url": { + "version": "3.972.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-format-url/-/util-format-url-3.972.7.tgz", + "integrity": "sha512-V+PbnWfUl93GuFwsOHsAq7hY/fnm9kElRqR8IexIJr5Rvif9e614X5sGSyz3mVSf1YAZ+VTy63W1/pGdA55zyA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/querystring-builder": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.5", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", + "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.972.7", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.7.tgz", + "integrity": "sha512-7SJVuvhKhMF/BkNS1n0QAJYgvEwYbK2QLKBrzDiwQGiTRU6Yf1f3nehTzm/l21xdAOtWSfp2uWSddPnP2ZtsVw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.973.4", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.4.tgz", + "integrity": "sha512-uqKeLqZ9D3nQjH7HGIERNXK9qnSpUK08l4MlJ5/NZqSSdeJsVANYp437EM9sEzwU28c2xfj2V6qlkqzsgtKs6Q==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-sdk/middleware-user-agent": "^3.972.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.10", + "resolved": "https://registry.npmmirror.com/@aws-sdk/xml-builder/-/xml-builder-3.972.10.tgz", + "integrity": "sha512-OnejAIVD+CxzyAUrVic7lG+3QRltyja9LoNqCE/1YVs8ichoTbJlVSaZ9iSMcnHLyzrSNtvaOGjSDRP+d/ouFA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "fast-xml-parser": "5.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.3.tgz", + "integrity": "sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@borewit/text-codec": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/@borewit/text-codec/-/text-codec-0.2.1.tgz", + "integrity": "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@buape/carbon": { + "version": "0.0.0-beta-20260216184201", + "resolved": "https://registry.npmmirror.com/@buape/carbon/-/carbon-0.0.0-beta-20260216184201.tgz", + "integrity": "sha512-u5mgYcigfPVqT7D9gVTGd+3YSflTreQmrWog7ORbb0z5w9eT8ft4rJOdw9fGwr75zMu9kXpSBaAcY2eZoJFSdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^25.0.9", + "discord-api-types": "0.38.37" + }, + "optionalDependencies": { + "@cloudflare/workers-types": "4.20260120.0", + "@discordjs/voice": "0.19.0", + "@hono/node-server": "1.19.9", + "@types/bun": "1.3.9", + "@types/ws": "8.18.1", + "ws": "8.19.0" + } + }, + "node_modules/@buape/carbon/node_modules/discord-api-types": { + "version": "0.38.37", + "resolved": "https://registry.npmmirror.com/discord-api-types/-/discord-api-types-0.38.37.tgz", + "integrity": "sha512-Cv47jzY1jkGkh5sv0bfHYqGgKOWO1peOrGMkDFM4UmaGMOTgOW8QSexhvixa9sVOiz8MnVOBryWYyw/CEVhj7w==", + "license": "MIT", + "peer": true, + "workspaces": [ + "scripts/actions/documentation" + ] + }, + "node_modules/@cacheable/memory": { + "version": "2.0.8", + "resolved": "https://registry.npmmirror.com/@cacheable/memory/-/memory-2.0.8.tgz", + "integrity": "sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@cacheable/utils": "^2.4.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/node-cache": { + "version": "1.7.6", + "resolved": "https://registry.npmmirror.com/@cacheable/node-cache/-/node-cache-1.7.6.tgz", + "integrity": "sha512-6Omk2SgNnjtxB5f/E6bTIWIt5xhdpx39fGNRQgU9lojvRxU68v+qY+SXXLsp3ZGukqoPjsK21wZ6XABFr/Ge3A==", + "license": "MIT", + "peer": true, + "dependencies": { + "cacheable": "^2.3.1", + "hookified": "^1.14.0", + "keyv": "^5.5.5" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/@cacheable/utils/-/utils-2.4.0.tgz", + "integrity": "sha512-PeMMsqjVq+bF0WBsxFBxr/WozBJiZKY0rUojuaCoIaKnEl3Ju1wfEwS+SV1DU/cSe8fqHIPiYJFif8T3MVt4cQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "hashery": "^1.5.0", + "keyv": "^5.6.0" + } + }, + "node_modules/@clack/core": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@clack/core/-/core-1.1.0.tgz", + "integrity": "sha512-SVcm4Dqm2ukn64/8Gub2wnlA5nS2iWJyCkdNHcvNHPIeBTGojpdJ+9cZKwLfmqy7irD4N5qLteSilJlE0WLAtA==", + "license": "MIT", + "peer": true, + "dependencies": { + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@clack/prompts/-/prompts-1.1.0.tgz", + "integrity": "sha512-pkqbPGtohJAvm4Dphs2M8xE29ggupihHdy1x84HNojZuMtFsHiUlRvqD24tM2+XmI+61LlfNceM3Wr7U5QES5g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@clack/core": "1.1.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20260120.0", + "resolved": "https://registry.npmmirror.com/@cloudflare/workers-types/-/workers-types-4.20260120.0.tgz", + "integrity": "sha512-B8pueG+a5S+mdK3z8oKu1ShcxloZ7qWb68IEyLLaepvdryIbNC7JVPcY0bWsjS56UQVKc5fnyRge3yZIwc9bxw==", + "license": "MIT OR Apache-2.0", + "optional": true, + "peer": true + }, + "node_modules/@discordjs/voice": { + "version": "0.19.0", + "resolved": "https://registry.npmmirror.com/@discordjs/voice/-/voice-0.19.0.tgz", + "integrity": "sha512-UyX6rGEXzVyPzb1yvjHtPfTlnLvB5jX/stAMdiytHhfoydX+98hfympdOwsnTktzr+IRvphxTbdErgYDJkEsvw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/ws": "^8.18.1", + "discord-api-types": "^0.38.16", + "prism-media": "^1.3.5", + "tslib": "^2.8.1", + "ws": "^8.18.3" + }, + "engines": { + "node": ">=22.12.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/voice/node_modules/prism-media": { + "version": "1.3.5", + "resolved": "https://registry.npmmirror.com/prism-media/-/prism-media-1.3.5.tgz", + "integrity": "sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==", + "license": "Apache-2.0", + "peer": true, + "peerDependencies": { + "@discordjs/opus": ">=0.8.0 <1.0.0", + "ffmpeg-static": "^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0", + "node-opus": "^0.3.3", + "opusscript": "^0.0.8" + }, + "peerDependenciesMeta": { + "@discordjs/opus": { + "optional": true + }, + "ffmpeg-static": { + "optional": true + }, + "node-opus": { + "optional": true + }, + "opusscript": { + "optional": true + } + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@google/genai": { + "version": "1.44.0", + "resolved": "https://registry.npmmirror.com/@google/genai/-/genai-1.44.0.tgz", + "integrity": "sha512-kRt9ZtuXmz+tLlcNntN/VV4LRdpl6ZOu5B1KbfNgfR65db15O6sUQcwnwLka8sT/V6qysD93fWrgJHF2L7dA9A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@grammyjs/runner": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/@grammyjs/runner/-/runner-2.0.3.tgz", + "integrity": "sha512-nckmTs1dPWfVQteK9cxqxzE+0m1VRvluLWB8UgFzsjg62w3qthPJt0TYtJBEdG7OedvfQq4vnFAyE6iaMkR42A==", + "license": "MIT", + "peer": true, + "dependencies": { + "abort-controller": "^3.0.0" + }, + "engines": { + "node": ">=12.20.0 || >=14.13.1" + }, + "peerDependencies": { + "grammy": "^1.13.1" + } + }, + "node_modules/@grammyjs/transformer-throttler": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@grammyjs/transformer-throttler/-/transformer-throttler-1.2.1.tgz", + "integrity": "sha512-CpWB0F3rJdUiKsq7826QhQsxbZi4wqfz1ccKX+fr+AOC+o8K7ZvS+wqX0suSu1QCsyUq2MDpNiKhyL2ZOJUS4w==", + "license": "MIT", + "peer": true, + "dependencies": { + "bottleneck": "^2.0.0" + }, + "engines": { + "node": "^12.20.0 || >=14.13.1" + }, + "peerDependencies": { + "grammy": "^1.0.0" + } + }, + "node_modules/@grammyjs/types": { + "version": "3.25.0", + "resolved": "https://registry.npmmirror.com/@grammyjs/types/-/types-3.25.0.tgz", + "integrity": "sha512-iN9i5p+8ZOu9OMxWNcguojQfz4K/PDyMPOnL7PPCON+SoA/F8OKMH3uR7CVUkYfdNe0GCz8QOzAWrnqusQYFOg==", + "license": "MIT", + "peer": true + }, + "node_modules/@hapi/boom": { + "version": "9.1.4", + "resolved": "https://registry.npmmirror.com/@hapi/boom/-/boom-9.1.4.tgz", + "integrity": "sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@hapi/hoek": "9.x.x" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@homebridge/ciao": { + "version": "1.3.5", + "resolved": "https://registry.npmmirror.com/@homebridge/ciao/-/ciao-1.3.5.tgz", + "integrity": "sha512-f7MAw7YuoEYgJEQ1VyRcLHGuVmCpmXi65GVR8CAtPWPqIZf/HFr4vHzVpOfQMpEQw9Pt5uh07guuLt5HE8ruog==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.3", + "fast-deep-equal": "^3.1.3", + "source-map-support": "^0.5.21", + "tslib": "^2.8.1" + }, + "bin": { + "ciao-bcs": "lib/bonjour-conformance-testing.js" + } + }, + "node_modules/@hono/node-server": { + "version": "1.19.9", + "resolved": "https://registry.npmmirror.com/@hono/node-server/-/node-server-1.19.9.tgz", + "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@huggingface/jinja": { + "version": "0.5.5", + "resolved": "https://registry.npmmirror.com/@huggingface/jinja/-/jinja-0.5.5.tgz", + "integrity": "sha512-xRlzazC+QZwr6z4ixEqYHo9fgwhTZ3xNSdljlKfUFGZSdlvt166DljRELFUfFytlYOYvo3vTisA/AFOuOAzFQQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT", + "peer": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" + } + }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "license": "MIT", + "peer": true + }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "license": "MIT", + "peer": true + }, + "node_modules/@larksuiteoapi/node-sdk": { + "version": "1.59.0", + "resolved": "https://registry.npmmirror.com/@larksuiteoapi/node-sdk/-/node-sdk-1.59.0.tgz", + "integrity": "sha512-sBpkruTvZDOxnVtoTbepWKRX0j1Y1ZElQYu0x7+v088sI9pcpbVp6ZzCGn62dhrKPatzNyCJyzYCPXPYQWccrA==", + "license": "MIT", + "peer": true, + "dependencies": { + "axios": "~1.13.3", + "lodash.identity": "^3.0.0", + "lodash.merge": "^4.6.2", + "lodash.pickby": "^4.6.0", + "protobufjs": "^7.2.6", + "qs": "^6.14.2", + "ws": "^8.19.0" + } + }, + "node_modules/@line/bot-sdk": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/@line/bot-sdk/-/bot-sdk-10.6.0.tgz", + "integrity": "sha512-4hSpglL/G/cW2JCcohaYz/BS0uOSJNV9IEYdMm0EiPEvDLayoI2hGq2D86uYPQFD2gvgkyhmzdShpWLG3P5r3w==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/node": "^24.0.0" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "axios": "^1.7.4" + } + }, + "node_modules/@line/bot-sdk/node_modules/@types/node": { + "version": "24.12.0", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@line/bot-sdk/node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT", + "peer": true + }, + "node_modules/@lydell/node-pty": { + "version": "1.2.0-beta.3", + "resolved": "https://registry.npmmirror.com/@lydell/node-pty/-/node-pty-1.2.0-beta.3.tgz", + "integrity": "sha512-ngGAItlRhmJXrhspxt8kX13n1dVFqzETOq0m/+gqSkO8NJBvNMwP7FZckMwps2UFySdr4yxCXNGu/bumg5at6A==", + "license": "MIT", + "peer": true, + "optionalDependencies": { + "@lydell/node-pty-darwin-arm64": "1.2.0-beta.3", + "@lydell/node-pty-darwin-x64": "1.2.0-beta.3", + "@lydell/node-pty-linux-arm64": "1.2.0-beta.3", + "@lydell/node-pty-linux-x64": "1.2.0-beta.3", + "@lydell/node-pty-win32-arm64": "1.2.0-beta.3", + "@lydell/node-pty-win32-x64": "1.2.0-beta.3" + } + }, + "node_modules/@lydell/node-pty-darwin-arm64": { + "version": "1.2.0-beta.3", + "resolved": "https://registry.npmmirror.com/@lydell/node-pty-darwin-arm64/-/node-pty-darwin-arm64-1.2.0-beta.3.tgz", + "integrity": "sha512-owcv+e1/OSu3bf9ZBdUQqJsQF888KyuSIiPYFNn0fLhgkhm9F3Pvha76Kj5mCPnodf7hh3suDe7upw7GPRXftQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@lydell/node-pty-darwin-x64": { + "version": "1.2.0-beta.3", + "resolved": "https://registry.npmmirror.com/@lydell/node-pty-darwin-x64/-/node-pty-darwin-x64-1.2.0-beta.3.tgz", + "integrity": "sha512-k38O+UviWrWdxtqZBBc/D8NJU11Rey8Y2YMwSWNxLv3eXZZdF5IVpbBkI/2RmLsV5nCcciqLPbukxeZnEfPlwA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@lydell/node-pty-linux-arm64": { + "version": "1.2.0-beta.3", + "resolved": "https://registry.npmmirror.com/@lydell/node-pty-linux-arm64/-/node-pty-linux-arm64-1.2.0-beta.3.tgz", + "integrity": "sha512-HUwRpGu3O+4sv9DAQFKnyW5LYhyYu2SDUa/bdFO/t4dIFCM4uDJEq47wfRM7+aYtJTi1b3lakN8SlWeuFQqJQQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@lydell/node-pty-linux-x64": { + "version": "1.2.0-beta.3", + "resolved": "https://registry.npmmirror.com/@lydell/node-pty-linux-x64/-/node-pty-linux-x64-1.2.0-beta.3.tgz", + "integrity": "sha512-+RRY0PoCUeQaCvPR7/UnkGbxulwbFtoTWJfe+o4T1RcNtngrgaI55I9nl8CD8uqhGrB3smKuyvPM5UtwGhASUw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@lydell/node-pty-win32-arm64": { + "version": "1.2.0-beta.3", + "resolved": "https://registry.npmmirror.com/@lydell/node-pty-win32-arm64/-/node-pty-win32-arm64-1.2.0-beta.3.tgz", + "integrity": "sha512-UEDd9ASp2M3iIYpIzfmfBlpyn4+K1G4CAjYcHWStptCkefoSVXWTiUBIa1KjBjZi3/xmsHIDpBEYTkGWuvLt2Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@lydell/node-pty-win32-x64": { + "version": "1.2.0-beta.3", + "resolved": "https://registry.npmmirror.com/@lydell/node-pty-win32-x64/-/node-pty-win32-x64-1.2.0-beta.3.tgz", + "integrity": "sha512-TpdqSFYx7/Rj+68tuP6F/lkRYrHCYAIJgaS1bx3SctTkb5QAQCFwOKHd4xlsivmEOMT2LdhkJggPxwX9PAO5pQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@mariozechner/clipboard": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard/-/clipboard-0.3.2.tgz", + "integrity": "sha512-IHQpksNjo7EAtGuHFU+tbWDp5LarH3HU/8WiB9O70ZEoBPHOg0/6afwSLK0QyNMMmx4Bpi/zl6+DcBXe95nWYA==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@mariozechner/clipboard-darwin-arm64": "0.3.2", + "@mariozechner/clipboard-darwin-universal": "0.3.2", + "@mariozechner/clipboard-darwin-x64": "0.3.2", + "@mariozechner/clipboard-linux-arm64-gnu": "0.3.2", + "@mariozechner/clipboard-linux-arm64-musl": "0.3.2", + "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.2", + "@mariozechner/clipboard-linux-x64-gnu": "0.3.2", + "@mariozechner/clipboard-linux-x64-musl": "0.3.2", + "@mariozechner/clipboard-win32-arm64-msvc": "0.3.2", + "@mariozechner/clipboard-win32-x64-msvc": "0.3.2" + } + }, + "node_modules/@mariozechner/clipboard-darwin-arm64": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-darwin-arm64/-/clipboard-darwin-arm64-0.3.2.tgz", + "integrity": "sha512-uBf6K7Je1ihsgvmWxA8UCGCeI+nbRVRXoarZdLjl6slz94Zs1tNKFZqx7aCI5O1i3e0B6ja82zZ06BWrl0MCVw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-darwin-universal": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-darwin-universal/-/clipboard-darwin-universal-0.3.2.tgz", + "integrity": "sha512-mxSheKTW2U9LsBdXy0SdmdCAE5HqNS9QUmpNHLnfJ+SsbFKALjEZc5oRrVMXxGQSirDvYf5bjmRyT0QYYonnlg==", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-darwin-x64": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-darwin-x64/-/clipboard-darwin-x64-0.3.2.tgz", + "integrity": "sha512-U1BcVEoidvwIp95+HJswSW+xr28EQiHR7rZjH6pn8Sja5yO4Yoe3yCN0Zm8Lo72BbSOK/fTSq0je7CJpaPCspg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-linux-arm64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-linux-arm64-gnu/-/clipboard-linux-arm64-gnu-0.3.2.tgz", + "integrity": "sha512-BsinwG3yWTIjdgNCxsFlip7LkfwPk+ruw/aFCXHUg/fb5XC/Ksp+YMQ7u0LUtiKzIv/7LMXgZInJQH6gxbAaqQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-linux-arm64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-linux-arm64-musl/-/clipboard-linux-arm64-musl-0.3.2.tgz", + "integrity": "sha512-0/Gi5Xq2V6goXBop19ePoHvXsmJD9SzFlO3S+d6+T2b+BlPcpOu3Oa0wTjl+cZrLAAEzA86aPNBI+VVAFDFPKw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-linux-riscv64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-linux-riscv64-gnu/-/clipboard-linux-riscv64-gnu-0.3.2.tgz", + "integrity": "sha512-2AFFiXB24qf0zOZsxI1GJGb9wQGlOJyN6UwoXqmKS3dpQi/l6ix30IzDDA4c4ZcCcx4D+9HLYXhC1w7Sov8pXA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-linux-x64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-linux-x64-gnu/-/clipboard-linux-x64-gnu-0.3.2.tgz", + "integrity": "sha512-v6fVnsn7WMGg73Dab8QMwyFce7tzGfgEixKgzLP8f1GJqkJZi5zO4k4FOHzSgUufgLil63gnxvMpjWkgfeQN7A==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-linux-x64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-linux-x64-musl/-/clipboard-linux-x64-musl-0.3.2.tgz", + "integrity": "sha512-xVUtnoMQ8v2JVyfJLKKXACA6avdnchdbBkTsZs8BgJQo29qwCp5NIHAUO8gbJ40iaEGToW5RlmVk2M9V0HsHEw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-win32-arm64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-win32-arm64-msvc/-/clipboard-win32-arm64-msvc-0.3.2.tgz", + "integrity": "sha512-AEgg95TNi8TGgak2wSXZkXKCvAUTjWoU1Pqb0ON7JHrX78p616XUFNTJohtIon3e0w6k0pYPZeCuqRCza/Tqeg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/clipboard-win32-x64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@mariozechner/clipboard-win32-x64-msvc/-/clipboard-win32-x64-msvc-0.3.2.tgz", + "integrity": "sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@mariozechner/jiti": { + "version": "2.6.5", + "resolved": "https://registry.npmmirror.com/@mariozechner/jiti/-/jiti-2.6.5.tgz", + "integrity": "sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==", + "license": "MIT", + "peer": true, + "dependencies": { + "std-env": "^3.10.0", + "yoctocolors": "^2.1.2" + }, + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/@mariozechner/pi-agent-core": { + "version": "0.57.1", + "resolved": "https://registry.npmmirror.com/@mariozechner/pi-agent-core/-/pi-agent-core-0.57.1.tgz", + "integrity": "sha512-WXsBbkNWOObFGHkhixaT8GXJpHDd3+fn8QntYF+4R8Sa9WB90ENXWidO6b7vcKX+JX0jjO5dIsQxmzosARJKlg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@mariozechner/pi-ai": "^0.57.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@mariozechner/pi-ai": { + "version": "0.57.1", + "resolved": "https://registry.npmmirror.com/@mariozechner/pi-ai/-/pi-ai-0.57.1.tgz", + "integrity": "sha512-Bd/J4a3YpdzJVyHLih0vDSdB0QPL4ti0XsAwtHOK/8eVhB0fHM1CpcgIrcBFJ23TMcKXMi0qamz18ERfp8tmgg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@anthropic-ai/sdk": "^0.73.0", + "@aws-sdk/client-bedrock-runtime": "^3.983.0", + "@google/genai": "^1.40.0", + "@mistralai/mistralai": "1.14.1", + "@sinclair/typebox": "^0.34.41", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "chalk": "^5.6.2", + "openai": "6.26.0", + "partial-json": "^0.1.7", + "proxy-agent": "^6.5.0", + "undici": "^7.19.1", + "zod-to-json-schema": "^3.24.6" + }, + "bin": { + "pi-ai": "dist/cli.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@mariozechner/pi-coding-agent": { + "version": "0.57.1", + "resolved": "https://registry.npmmirror.com/@mariozechner/pi-coding-agent/-/pi-coding-agent-0.57.1.tgz", + "integrity": "sha512-u5MQEduj68rwVIsRsqrWkJYiJCyPph/a6bMoJAQKo1sb+Pc17Y/ojwa+wGssnUMjEB38AQKofWTVe8NFEpSWNw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@mariozechner/jiti": "^2.6.2", + "@mariozechner/pi-agent-core": "^0.57.1", + "@mariozechner/pi-ai": "^0.57.1", + "@mariozechner/pi-tui": "^0.57.1", + "@silvia-odwyer/photon-node": "^0.3.4", + "chalk": "^5.5.0", + "cli-highlight": "^2.1.11", + "diff": "^8.0.2", + "extract-zip": "^2.0.1", + "file-type": "^21.1.1", + "glob": "^13.0.1", + "hosted-git-info": "^9.0.2", + "ignore": "^7.0.5", + "marked": "^15.0.12", + "minimatch": "^10.2.3", + "proper-lockfile": "^4.1.2", + "strip-ansi": "^7.1.0", + "undici": "^7.19.1", + "yaml": "^2.8.2" + }, + "bin": { + "pi": "dist/cli.js" + }, + "engines": { + "node": ">=20.6.0" + }, + "optionalDependencies": { + "@mariozechner/clipboard": "^0.3.2" + } + }, + "node_modules/@mariozechner/pi-tui": { + "version": "0.57.1", + "resolved": "https://registry.npmmirror.com/@mariozechner/pi-tui/-/pi-tui-0.57.1.tgz", + "integrity": "sha512-cjoRghLbeAHV0tTJeHgZXaryUi5zzBZofeZ7uJun1gztnckLLRjoVeaPTujNlc5BIfyKvFqhh1QWCZng/MXlpg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/mime-types": "^2.1.4", + "chalk": "^5.5.0", + "get-east-asian-width": "^1.3.0", + "marked": "^15.0.12", + "mime-types": "^3.0.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "optionalDependencies": { + "koffi": "^2.9.0" + } + }, + "node_modules/@mistralai/mistralai": { + "version": "1.14.1", + "resolved": "https://registry.npmmirror.com/@mistralai/mistralai/-/mistralai-1.14.1.tgz", + "integrity": "sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ==", + "peer": true, + "dependencies": { + "ws": "^8.18.0", + "zod": "^3.25.0 || ^4.0.0", + "zod-to-json-schema": "^3.24.1" + } + }, + "node_modules/@mozilla/readability": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/@mozilla/readability/-/readability-0.6.0.tgz", + "integrity": "sha512-juG5VWh4qAivzTAeMzvY9xs9HY5rAcr2E4I7tiSSCokRFi7XIZCAu92ZkSTsIj1OPceCifL3cpfteP3pDT9/QQ==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@napi-rs/canvas": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas/-/canvas-0.1.96.tgz", + "integrity": "sha512-6NNmNxvoJKeucVjxaaRUt3La2i5jShgiAbaY3G/72s1Vp3U06XPrAIxkAjBxpDcamEn/t+WJ4OOlGmvILo4/Ew==", + "license": "MIT", + "peer": true, + "workspaces": [ + "e2e/*" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.96", + "@napi-rs/canvas-darwin-arm64": "0.1.96", + "@napi-rs/canvas-darwin-x64": "0.1.96", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.96", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.96", + "@napi-rs/canvas-linux-arm64-musl": "0.1.96", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.96", + "@napi-rs/canvas-linux-x64-gnu": "0.1.96", + "@napi-rs/canvas-linux-x64-musl": "0.1.96", + "@napi-rs/canvas-win32-arm64-msvc": "0.1.96", + "@napi-rs/canvas-win32-x64-msvc": "0.1.96" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.96.tgz", + "integrity": "sha512-ew1sPrN3dGdZ3L4FoohPfnjq0f9/Jk7o+wP7HkQZokcXgIUD6FIyICEWGhMYzv53j63wUcPvZeAwgewX58/egg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.96.tgz", + "integrity": "sha512-Q/wOXZ5PzTqpdmA5eUOcegCf4Go/zz3aZ5DlzSeDpOjFmfwMKh8EzLAoweQ+mJVagcHQyzoJhaTEnrO68TNyNg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.96.tgz", + "integrity": "sha512-UrXiQz28tQEvGM1qvyptewOAfmUrrd5+wvi6Rzjj2VprZI8iZ2KIvBD2lTTG1bVF95AbeDeG7PJA0D9sLKaOFA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.96.tgz", + "integrity": "sha512-I90ODxweD8aEP6XKU/NU+biso95MwCtQ2F46dUvhec1HesFi0tq/tAJkYic/1aBSiO/1kGKmSeD1B0duOHhEHQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.96.tgz", + "integrity": "sha512-Dx/0+RFV++w3PcRy+4xNXkghhXjA5d0Mw1bs95emn5Llinp1vihMaA6WJt3oYv2LAHc36+gnrhIBsPhUyI2SGw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.96.tgz", + "integrity": "sha512-UvOi7fii3IE2KDfEfhh8m+LpzSRvhGK7o1eho99M2M0HTik11k3GX+2qgVx9EtujN3/bhFFS1kSO3+vPMaJ0Mg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.96.tgz", + "integrity": "sha512-MBSukhGCQ5nRtf9NbFYWOU080yqkZU1PbuH4o1ROvB4CbPl12fchDR35tU83Wz8gWIM9JTn99lBn9DenPIv7Ig==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.96.tgz", + "integrity": "sha512-I/ccu2SstyKiV3HIeVzyBIWfrJo8cN7+MSQZPnabewWV6hfJ2nY7Df2WqOHmobBRUw84uGR6zfQHsUEio/m5Vg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.96.tgz", + "integrity": "sha512-H3uov7qnTl73GDT4h52lAqpJPsl1tIUyNPWJyhQ6gHakohNqqRq3uf80+NEpzcytKGEOENP1wX3yGwZxhjiWEQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-arm64-msvc": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.96.tgz", + "integrity": "sha512-ATp6Y+djOjYtkfV/VRH7CZ8I1MEtkUQBmKUbuWw5zWEHHqfL0cEcInE4Cxgx7zkNAhEdBbnH8HMVrqNp+/gwxA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "0.1.96", + "resolved": "https://registry.npmmirror.com/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.96.tgz", + "integrity": "sha512-UYGdTltVd+Z8mcIuoqGmAXXUvwH5CLf2M6mIB5B0/JmX5J041jETjqtSYl7gN+aj3k1by/SG6sS0hAwCqyK7zw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@node-llama-cpp/linux-arm64": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/linux-arm64/-/linux-arm64-3.16.2.tgz", + "integrity": "sha512-CxzgPsS84wL3W5sZRgxP3c9iJKEW+USrak1SmX6EAJxW/v9QGzehvT6W/aR1FyfidiIyQtOp3ga0Gg/9xfJPGw==", + "cpu": [ + "arm64", + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@node-llama-cpp/linux-armv7l": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/linux-armv7l/-/linux-armv7l-3.16.2.tgz", + "integrity": "sha512-9G6W/MkQ/DLwGmpcj143NQ50QJg5gQZfzVf5RYx77VczBqhgwkgYHILekYrOs4xanOeqeJ8jnOnQQSp1YaJZUg==", + "cpu": [ + "arm", + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@node-llama-cpp/linux-x64": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/linux-x64/-/linux-x64-3.16.2.tgz", + "integrity": "sha512-OXYf8rVfoDyvN+YrfKk8F9An9a5GOxVIM8OcR1U911tc0oRNf8yfJrQ8KrM75R26gwq0Y6YZwVTP0vRCInwWOw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@node-llama-cpp/linux-x64-vulkan": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/linux-x64-vulkan/-/linux-x64-vulkan-3.16.2.tgz", + "integrity": "sha512-HDLAw4ZhwJuhKuF6n4x520yZXAQZahUOXtCGvPubjfpmIOElKrfDvCVlRsthAP0JwcwINzIQlVys3boMIXfBgw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@node-llama-cpp/mac-arm64-metal": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/mac-arm64-metal/-/mac-arm64-metal-3.16.2.tgz", + "integrity": "sha512-nEZ74qB0lUohF88yR741YUrUqz/qD+FJFzUTHj0FwxAynSZCjvwtzEDtavRlh3qd3yLD/0ChNn00/RQ54ISImw==", + "cpu": [ + "arm64", + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@node-llama-cpp/mac-x64": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/mac-x64/-/mac-x64-3.16.2.tgz", + "integrity": "sha512-BjA+DgeDt+kRxVMV6kChb9XVXm7U5b90jUif7Z/s6ZXtOOnV6exrTM2W09kbSqAiNhZmctcVY83h2dwNTZ/yIw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@node-llama-cpp/win-arm64": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/win-arm64/-/win-arm64-3.16.2.tgz", + "integrity": "sha512-XHNFQzUjYODtkZjIn4NbQVrBtGB9RI9TpisiALryqfrIqagQmjBh6dmxZWlt5uduKAfT7M2/2vrABGR490FACA==", + "cpu": [ + "arm64", + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@node-llama-cpp/win-x64": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/@node-llama-cpp/win-x64/-/win-x64-3.16.2.tgz", + "integrity": "sha512-etrivzbyLNVhZlUosFW8JSL0OSiuKQf9qcI3dNdehD907sHquQbBJrG7lXcdL6IecvXySp3oAwCkM87VJ0b3Fg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@octokit/app": { + "version": "16.1.2", + "resolved": "https://registry.npmmirror.com/@octokit/app/-/app-16.1.2.tgz", + "integrity": "sha512-8j7sEpUYVj18dxvh0KWj6W/l6uAiVRBl1JBDVRqH1VHKAO/G5eRVl4yEoYACjakWers1DjUkcCHyJNQK47JqyQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-app": "^8.1.2", + "@octokit/auth-unauthenticated": "^7.0.3", + "@octokit/core": "^7.0.6", + "@octokit/oauth-app": "^8.0.3", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/types": "^16.0.0", + "@octokit/webhooks": "^14.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/auth-app": { + "version": "8.2.0", + "resolved": "https://registry.npmmirror.com/@octokit/auth-app/-/auth-app-8.2.0.tgz", + "integrity": "sha512-vVjdtQQwomrZ4V46B9LaCsxsySxGoHsyw6IYBov/TqJVROrlYdyNgw5q6tQbB7KZt53v1l1W53RiqTvpzL907g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-oauth-app": "^9.0.3", + "@octokit/auth-oauth-user": "^6.0.2", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "toad-cache": "^3.7.0", + "universal-github-app-jwt": "^2.2.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/auth-oauth-app": { + "version": "9.0.3", + "resolved": "https://registry.npmmirror.com/@octokit/auth-oauth-app/-/auth-oauth-app-9.0.3.tgz", + "integrity": "sha512-+yoFQquaF8OxJSxTb7rnytBIC2ZLbLqA/yb71I4ZXT9+Slw4TziV9j/kyGhUFRRTF2+7WlnIWsePZCWHs+OGjg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-oauth-device": "^8.0.3", + "@octokit/auth-oauth-user": "^6.0.2", + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/auth-oauth-device": { + "version": "8.0.3", + "resolved": "https://registry.npmmirror.com/@octokit/auth-oauth-device/-/auth-oauth-device-8.0.3.tgz", + "integrity": "sha512-zh2W0mKKMh/VWZhSqlaCzY7qFyrgd9oTWmTmHaXnHNeQRCZr/CXy2jCgHo4e4dJVTiuxP5dLa0YM5p5QVhJHbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/oauth-methods": "^6.0.2", + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/auth-oauth-user": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/@octokit/auth-oauth-user/-/auth-oauth-user-6.0.2.tgz", + "integrity": "sha512-qLoPPc6E6GJoz3XeDG/pnDhJpTkODTGG4kY0/Py154i/I003O9NazkrwJwRuzgCalhzyIeWQ+6MDvkUmKXjg/A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-oauth-device": "^8.0.3", + "@octokit/oauth-methods": "^6.0.2", + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/auth-unauthenticated": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/@octokit/auth-unauthenticated/-/auth-unauthenticated-7.0.3.tgz", + "integrity": "sha512-8Jb1mtUdmBHL7lGmop9mU9ArMRUTRhg8vp0T1VtZ4yd9vEm3zcLwmjQkhNEduKawOOORie61xhtYIhTDN+ZQ3g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/core": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/@octokit/core/-/core-7.0.6.tgz", + "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.3", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/endpoint": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/@octokit/endpoint/-/endpoint-11.0.3.tgz", + "integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/graphql": { + "version": "9.0.3", + "resolved": "https://registry.npmmirror.com/@octokit/graphql/-/graphql-9.0.3.tgz", + "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/oauth-app": { + "version": "8.0.3", + "resolved": "https://registry.npmmirror.com/@octokit/oauth-app/-/oauth-app-8.0.3.tgz", + "integrity": "sha512-jnAjvTsPepyUaMu9e69hYBuozEPgYqP4Z3UnpmvoIzHDpf8EXDGvTY1l1jK0RsZ194oRd+k6Hm13oRU8EoDFwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-oauth-app": "^9.0.2", + "@octokit/auth-oauth-user": "^6.0.1", + "@octokit/auth-unauthenticated": "^7.0.2", + "@octokit/core": "^7.0.5", + "@octokit/oauth-authorization-url": "^8.0.0", + "@octokit/oauth-methods": "^6.0.1", + "@types/aws-lambda": "^8.10.83", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/oauth-authorization-url": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-8.0.0.tgz", + "integrity": "sha512-7QoLPRh/ssEA/HuHBHdVdSgF8xNLz/Bc5m9fZkArJE5bb6NmVkDm3anKxXPmN1zh6b5WKZPRr3697xKT/yM3qQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/oauth-methods": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/@octokit/oauth-methods/-/oauth-methods-6.0.2.tgz", + "integrity": "sha512-HiNOO3MqLxlt5Da5bZbLV8Zarnphi4y9XehrbaFMkcoJ+FL7sMxH/UlUsCVxpddVu4qvNDrBdaTVE2o4ITK8ng==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/oauth-authorization-url": "^8.0.0", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "27.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", + "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", + "license": "MIT", + "peer": true + }, + "node_modules/@octokit/openapi-webhooks-types": { + "version": "12.1.0", + "resolved": "https://registry.npmmirror.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-12.1.0.tgz", + "integrity": "sha512-WiuzhOsiOvb7W3Pvmhf8d2C6qaLHXrWiLBP4nJ/4kydu+wpagV5Fkz9RfQwV2afYzv3PB+3xYgp4mAdNGjDprA==", + "license": "MIT", + "peer": true + }, + "node_modules/@octokit/plugin-paginate-graphql": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-6.0.0.tgz", + "integrity": "sha512-crfpnIoFiBtRkvPqOyLOsw12XsveYuY2ieP6uYDosoUegBJpSVxGwut9sxUgFFcll3VTOTqpUf8yGd8x1OmAkQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "14.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz", + "integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "17.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", + "integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/@octokit/plugin-retry/-/plugin-retry-8.1.0.tgz", + "integrity": "sha512-O1FZgXeiGb2sowEr/hYTr6YunGdSAFWnr2fyW39Ah85H8O33ELASQxcvOFF5LE6Tjekcyu2ms4qAzJVhSaJxTw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=7" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "11.0.3", + "resolved": "https://registry.npmmirror.com/@octokit/plugin-throttling/-/plugin-throttling-11.0.3.tgz", + "integrity": "sha512-34eE0RkFCKycLl2D2kq7W+LovheM/ex3AwZCYN8udpi6bxsyjZidb2McXs69hZhLmJlDqTSP8cH+jSRpiaijBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/types": "^16.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": "^7.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "10.0.8", + "resolved": "https://registry.npmmirror.com/@octokit/request/-/request-10.0.8.tgz", + "integrity": "sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/endpoint": "^11.0.3", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "fast-content-type-parse": "^3.0.0", + "json-with-bigint": "^3.5.3", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/request-error": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/@octokit/request-error/-/request-error-7.1.0.tgz", + "integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/types": { + "version": "16.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/types/-/types-16.0.0.tgz", + "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/openapi-types": "^27.0.0" + } + }, + "node_modules/@octokit/webhooks": { + "version": "14.2.0", + "resolved": "https://registry.npmmirror.com/@octokit/webhooks/-/webhooks-14.2.0.tgz", + "integrity": "sha512-da6KbdNCV5sr1/txD896V+6W0iamFWrvVl8cHkBSPT+YlvmT3DwXa4jxZnQc+gnuTEqSWbBeoSZYTayXH9wXcw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/openapi-webhooks-types": "12.1.0", + "@octokit/request-error": "^7.0.0", + "@octokit/webhooks-methods": "^6.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/webhooks-methods": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/@octokit/webhooks-methods/-/webhooks-methods-6.0.0.tgz", + "integrity": "sha512-MFlzzoDJVw/GcbfzVC1RLR36QqkTLUf79vLVO3D+xn7r0QgxnFoLZgtrzxiQErAjFUOdH6fas2KeQJ1yr/qaXQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT", + "peer": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@reflink/reflink": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink/-/reflink-0.1.19.tgz", + "integrity": "sha512-DmCG8GzysnCZ15bres3N5AHCmwBwYgp0As6xjhQ47rAUTUXxJiK+lLUxaGsX3hd/30qUpVElh05PbGuxRPgJwA==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@reflink/reflink-darwin-arm64": "0.1.19", + "@reflink/reflink-darwin-x64": "0.1.19", + "@reflink/reflink-linux-arm64-gnu": "0.1.19", + "@reflink/reflink-linux-arm64-musl": "0.1.19", + "@reflink/reflink-linux-x64-gnu": "0.1.19", + "@reflink/reflink-linux-x64-musl": "0.1.19", + "@reflink/reflink-win32-arm64-msvc": "0.1.19", + "@reflink/reflink-win32-x64-msvc": "0.1.19" + } + }, + "node_modules/@reflink/reflink-darwin-arm64": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-darwin-arm64/-/reflink-darwin-arm64-0.1.19.tgz", + "integrity": "sha512-ruy44Lpepdk1FqDz38vExBY/PVUsjxZA+chd9wozjUH9JjuDT/HEaQYA6wYN9mf041l0yLVar6BCZuWABJvHSA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@reflink/reflink-darwin-x64": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-darwin-x64/-/reflink-darwin-x64-0.1.19.tgz", + "integrity": "sha512-By85MSWrMZa+c26TcnAy8SDk0sTUkYlNnwknSchkhHpGXOtjNDUOxJE9oByBnGbeuIE1PiQsxDG3Ud+IVV9yuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@reflink/reflink-linux-arm64-gnu": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-linux-arm64-gnu/-/reflink-linux-arm64-gnu-0.1.19.tgz", + "integrity": "sha512-7P+er8+rP9iNeN+bfmccM4hTAaLP6PQJPKWSA4iSk2bNvo6KU6RyPgYeHxXmzNKzPVRcypZQTpFgstHam6maVg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@reflink/reflink-linux-arm64-musl": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-linux-arm64-musl/-/reflink-linux-arm64-musl-0.1.19.tgz", + "integrity": "sha512-37iO/Dp6m5DDaC2sf3zPtx/hl9FV3Xze4xoYidrxxS9bgP3S8ALroxRK6xBG/1TtfXKTvolvp+IjrUU6ujIGmA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@reflink/reflink-linux-x64-gnu": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-linux-x64-gnu/-/reflink-linux-x64-gnu-0.1.19.tgz", + "integrity": "sha512-jbI8jvuYCaA3MVUdu8vLoLAFqC+iNMpiSuLbxlAgg7x3K5bsS8nOpTRnkLF7vISJ+rVR8W+7ThXlXlUQ93ulkw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@reflink/reflink-linux-x64-musl": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-linux-x64-musl/-/reflink-linux-x64-musl-0.1.19.tgz", + "integrity": "sha512-e9FBWDe+lv7QKAwtKOt6A2W/fyy/aEEfr0g6j/hWzvQcrzHCsz07BNQYlNOjTfeytrtLU7k449H1PI95jA4OjQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@reflink/reflink-win32-arm64-msvc": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-win32-arm64-msvc/-/reflink-win32-arm64-msvc-0.1.19.tgz", + "integrity": "sha512-09PxnVIQcd+UOn4WAW73WU6PXL7DwGS6wPlkMhMg2zlHHG65F3vHepOw06HFCq+N42qkaNAc8AKIabWvtk6cIQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@reflink/reflink-win32-x64-msvc": { + "version": "0.1.19", + "resolved": "https://registry.npmmirror.com/@reflink/reflink-win32-x64-msvc/-/reflink-win32-x64-msvc-0.1.19.tgz", + "integrity": "sha512-E//yT4ni2SyhwP8JRjVGWr3cbnhWDiPLgnQ66qqaanjjnMiu3O/2tjCPQXlcGc/DEYofpDc9fvhv6tALQsMV9w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@silvia-odwyer/photon-node": { + "version": "0.3.4", + "resolved": "https://registry.npmmirror.com/@silvia-odwyer/photon-node/-/photon-node-0.3.4.tgz", + "integrity": "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "license": "MIT", + "peer": true + }, + "node_modules/@slack/bolt": { + "version": "4.6.0", + "resolved": "https://registry.npmmirror.com/@slack/bolt/-/bolt-4.6.0.tgz", + "integrity": "sha512-xPgfUs2+OXSugz54Ky07pA890+Qydk22SYToi8uGpXeHSt1JWwFJkRyd/9Vlg5I1AdfdpGXExDpwnbuN9Q/2dQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@slack/logger": "^4.0.0", + "@slack/oauth": "^3.0.4", + "@slack/socket-mode": "^2.0.5", + "@slack/types": "^2.18.0", + "@slack/web-api": "^7.12.0", + "axios": "^1.12.0", + "express": "^5.0.0", + "path-to-regexp": "^8.1.0", + "raw-body": "^3", + "tsscmp": "^1.0.6" + }, + "engines": { + "node": ">=18", + "npm": ">=8.6.0" + }, + "peerDependencies": { + "@types/express": "^5.0.0" + } + }, + "node_modules/@slack/logger": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/@slack/logger/-/logger-4.0.0.tgz", + "integrity": "sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": ">=18.0.0" + }, + "engines": { + "node": ">= 18", + "npm": ">= 8.6.0" + } + }, + "node_modules/@slack/oauth": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@slack/oauth/-/oauth-3.0.4.tgz", + "integrity": "sha512-+8H0g7mbrHndEUbYCP7uYyBCbwqmm3E6Mo3nfsDvZZW74zKk1ochfH/fWSvGInYNCVvaBUbg3RZBbTp0j8yJCg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@slack/logger": "^4", + "@slack/web-api": "^7.10.0", + "@types/jsonwebtoken": "^9", + "@types/node": ">=18", + "jsonwebtoken": "^9" + }, + "engines": { + "node": ">=18", + "npm": ">=8.6.0" + } + }, + "node_modules/@slack/socket-mode": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@slack/socket-mode/-/socket-mode-2.0.5.tgz", + "integrity": "sha512-VaapvmrAifeFLAFaDPfGhEwwunTKsI6bQhYzxRXw7BSujZUae5sANO76WqlVsLXuhVtCVrBWPiS2snAQR2RHJQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@slack/logger": "^4", + "@slack/web-api": "^7.10.0", + "@types/node": ">=18", + "@types/ws": "^8", + "eventemitter3": "^5", + "ws": "^8" + }, + "engines": { + "node": ">= 18", + "npm": ">= 8.6.0" + } + }, + "node_modules/@slack/types": { + "version": "2.20.0", + "resolved": "https://registry.npmmirror.com/@slack/types/-/types-2.20.0.tgz", + "integrity": "sha512-PVF6P6nxzDMrzPC8fSCsnwaI+kF8YfEpxf3MqXmdyjyWTYsZQURpkK7WWUWvP5QpH55pB7zyYL9Qem/xSgc5VA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 12.13.0", + "npm": ">= 6.12.0" + } + }, + "node_modules/@slack/web-api": { + "version": "7.14.1", + "resolved": "https://registry.npmmirror.com/@slack/web-api/-/web-api-7.14.1.tgz", + "integrity": "sha512-RoygyteJeFswxDPJjUMESn9dldWVMD2xUcHHd9DenVavSfVC6FeVnSdDerOO7m8LLvw4Q132nQM4hX8JiF7dng==", + "license": "MIT", + "peer": true, + "dependencies": { + "@slack/logger": "^4.0.0", + "@slack/types": "^2.20.0", + "@types/node": ">=18.0.0", + "@types/retry": "0.12.0", + "axios": "^1.13.5", + "eventemitter3": "^5.0.1", + "form-data": "^4.0.4", + "is-electron": "2.2.2", + "is-stream": "^2", + "p-queue": "^6", + "p-retry": "^4", + "retry": "^0.13.1" + }, + "engines": { + "node": ">= 18", + "npm": ">= 8.6.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/abort-controller/-/abort-controller-4.2.11.tgz", + "integrity": "sha512-Hj4WoYWMJnSpM6/kchsm4bUNTL9XiSyhvoMb2KIq4VJzyDt7JpGHUZHkVNPZVC7YE1tf8tPeVauxpFBKGW4/KQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.10", + "resolved": "https://registry.npmmirror.com/@smithy/config-resolver/-/config-resolver-4.4.10.tgz", + "integrity": "sha512-IRTkd6ps0ru+lTWnfnsbXzW80A8Od8p3pYiZnW98K2Hb20rqfsX7VTlfUwhrcOeSSy68Gn9WBofwPuw3e5CCsg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-endpoints": "^3.3.2", + "@smithy/util-middleware": "^4.2.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.23.9", + "resolved": "https://registry.npmmirror.com/@smithy/core/-/core-3.23.9.tgz", + "integrity": "sha512-1Vcut4LEL9HZsdpI0vFiRYIsaoPwZLjAxnVQDUMQK8beMS+EYPLDQCXtbzfxmM5GzSgjfe2Q9M7WaXwIMQllyQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/middleware-serde": "^4.2.12", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.11.tgz", + "integrity": "sha512-lBXrS6ku0kTj3xLmsJW0WwqWbGQ6ueooYyp/1L9lkyT0M02C+DWwYwc5aTyXFbRaK38ojALxNixg+LxKSHZc0g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^4.3.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-codec/-/eventstream-codec-4.2.11.tgz", + "integrity": "sha512-Sf39Ml0iVX+ba/bgMPxaXWAAFmHqYLTmbjAPfLPLY8CrYkRDEqZdUsKC1OwVMCdJXfAt0v4j49GIJ8DoSYAe6w==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.13.0", + "@smithy/util-hex-encoding": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.11.tgz", + "integrity": "sha512-3rEpo3G6f/nRS7fQDsZmxw/ius6rnlIpz4UX6FlALEzz8JoSxFmdBt0SZnthis+km7sQo6q5/3e+UJcuQivoXA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.11", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.11.tgz", + "integrity": "sha512-XeNIA8tcP/GDWnnKkO7qEm/bg0B/bP9lvIXZBXcGZwZ+VYM8h8k9wuDvUODtdQ2Wcp2RcBkPTCSMmaniVHrMlA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.11.tgz", + "integrity": "sha512-fzbCh18rscBDTQSCrsp1fGcclLNF//nJyhjldsEl/5wCYmgpHblv5JSppQAyQI24lClsFT0wV06N1Porn0IsEw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.11.tgz", + "integrity": "sha512-MJ7HcI+jEkqoWT5vp+uoVaAjBrmxBtKhZTeynDRG/seEjJfqyg3SiqMMqyPnAMzmIfLaeJ/uiuSDP/l9AnMy/Q==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/eventstream-codec": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.13", + "resolved": "https://registry.npmmirror.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.13.tgz", + "integrity": "sha512-U2Hcfl2s3XaYjikN9cT4mPu8ybDbImV3baXR0PkVlC0TTx808bRP3FaPGAzPtB8OByI+JqJ1kyS+7GEgae7+qQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/protocol-http": "^5.3.11", + "@smithy/querystring-builder": "^4.2.11", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/hash-node/-/hash-node-4.2.11.tgz", + "integrity": "sha512-T+p1pNynRkydpdL015ruIoyPSRw9e/SQOWmSAMmmprfswMrd5Ow5igOWNVlvyVFZlxXqGmyH3NQwfwy8r5Jx0A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/invalid-dependency/-/invalid-dependency-4.2.11.tgz", + "integrity": "sha512-cGNMrgykRmddrNhYy1yBdrp5GwIgEkniS7k9O1VLB38yxQtlvrxpZtUVvo6T4cKpeZsriukBuuxfJcdZQc/f/g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", + "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-content-length/-/middleware-content-length-4.2.11.tgz", + "integrity": "sha512-UvIfKYAKhCzr4p6jFevPlKhQwyQwlJ6IeKLDhmV1PlYfcW3RL4ROjNEDtSik4NYMi9kDkH7eSwyTP3vNJ/u/Dw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.4.23", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.23.tgz", + "integrity": "sha512-UEFIejZy54T1EJn2aWJ45voB7RP2T+IRzUqocIdM6GFFa5ClZncakYJfcYnoXt3UsQrZZ9ZRauGm77l9UCbBLw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/core": "^3.23.9", + "@smithy/middleware-serde": "^4.2.12", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-middleware": "^4.2.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.40", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-retry/-/middleware-retry-4.4.40.tgz", + "integrity": "sha512-YhEMakG1Ae57FajERdHNZ4ShOPIY7DsgV+ZoAxo/5BT0KIe+f6DDU2rtIymNNFIj22NJfeeI6LWIifrwM0f+rA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^4.3.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/service-error-classification": "^4.2.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-retry": "^4.2.11", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.2.12", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-serde/-/middleware-serde-4.2.12.tgz", + "integrity": "sha512-W9g1bOLui7Xn5FABRVS0o3rXL0gfN37d/8I/W7i0N7oxjx9QecUmXEMSUMADTODwdtka9cN43t5BI2CodLJpng==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-stack/-/middleware-stack-4.2.11.tgz", + "integrity": "sha512-s+eenEPW6RgliDk2IhjD2hWOxIx1NKrOHxEwNUaUXxYBxIyCcDfNULZ2Mu15E3kwcJWBedTET/kEASPV1A1Akg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.3.11", + "resolved": "https://registry.npmmirror.com/@smithy/node-config-provider/-/node-config-provider-4.3.11.tgz", + "integrity": "sha512-xD17eE7kaLgBBGf5CZQ58hh2YmwK1Z0O8YhffwB/De2jsL0U3JklmhVYJ9Uf37OtUDLF2gsW40Xwwag9U869Gg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.4.14", + "resolved": "https://registry.npmmirror.com/@smithy/node-http-handler/-/node-http-handler-4.4.14.tgz", + "integrity": "sha512-DamSqaU8nuk0xTJDrYnRzZndHwwRnyj/n/+RqGGCcBKB4qrQem0mSDiWdupaNWdwxzyMU91qxDmHOCazfhtO3A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/abort-controller": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/querystring-builder": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/property-provider/-/property-provider-4.2.11.tgz", + "integrity": "sha512-14T1V64o6/ndyrnl1ze1ZhyLzIeYNN47oF/QU6P5m82AEtyOkMJTb0gO1dPubYjyyKuPD6OSVMPDKe+zioOnCg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "5.3.11", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.11.tgz", + "integrity": "sha512-hI+barOVDJBkNt4y0L2mu3Ugc0w7+BpJ2CZuLwXtSltGAAwCb3IvnalGlbDV/UCS6a9ZuT3+exd1WxNdLb5IlQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/querystring-builder/-/querystring-builder-4.2.11.tgz", + "integrity": "sha512-7spdikrYiljpket6u0up2Ck2mxhy7dZ0+TDd+S53Dg2DHd6wg+YNJrTCHiLdgZmEXZKI7LJZcwL3721ZRDFiqA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "@smithy/util-uri-escape": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/querystring-parser/-/querystring-parser-4.2.11.tgz", + "integrity": "sha512-nE3IRNjDltvGcoThD2abTozI1dkSy8aX+a2N1Rs55en5UsdyyIXgGEmevUL3okZFoJC77JgRGe99xYohhsjivQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/service-error-classification/-/service-error-classification-4.2.11.tgz", + "integrity": "sha512-HkMFJZJUhzU3HvND1+Yw/kYWXp4RPDLBWLcK1n+Vqw8xn4y2YiBhdww8IxhkQjP/QlZun5bwm3vcHc8AqIU3zw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.4.6", + "resolved": "https://registry.npmmirror.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.6.tgz", + "integrity": "sha512-IB/M5I8G0EeXZTHsAxpx51tMQ5R719F3aq+fjEB6VtNcCHDc0ajFDIGDZw+FW9GxtEkgTduiPpjveJdA/CX7sw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.3.11", + "resolved": "https://registry.npmmirror.com/@smithy/signature-v4/-/signature-v4-5.3.11.tgz", + "integrity": "sha512-V1L6N9aKOBAN4wEHLyqjLBnAz13mtILU0SeDrjOaIZEeN6IFa6DxwRt1NNpOdmSpQUfkBj0qeD3m6P77uzMhgQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-uri-escape": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.12.3", + "resolved": "https://registry.npmmirror.com/@smithy/smithy-client/-/smithy-client-4.12.3.tgz", + "integrity": "sha512-7k4UxjSpHmPN2AxVhvIazRSzFQjWnud3sOsXcFStzagww17j1cFQYqTSiQ8xuYK3vKLR1Ni8FzuT3VlKr3xCNw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/core": "^3.23.9", + "@smithy/middleware-endpoint": "^4.4.23", + "@smithy/middleware-stack": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-stream": "^4.5.17", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.13.0", + "resolved": "https://registry.npmmirror.com/@smithy/types/-/types-4.13.0.tgz", + "integrity": "sha512-COuLsZILbbQsdrwKQpkkpyep7lCsByxwj7m0Mg5v66/ZTyenlfBc40/QFQ5chO0YN/PNEH1Bi3fGtfXPnYNeDw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/url-parser/-/url-parser-4.2.11.tgz", + "integrity": "sha512-oTAGGHo8ZYc5VZsBREzuf5lf2pAurJQsccMusVZ85wDkX66ojEc/XauiGjzCj50A61ObFTPe6d7Pyt6UBYaing==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/querystring-parser": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.3.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-base64/-/util-base64-4.3.2.tgz", + "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz", + "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz", + "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz", + "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/is-array-buffer": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz", + "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.39", + "resolved": "https://registry.npmmirror.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.39.tgz", + "integrity": "sha512-ui7/Ho/+VHqS7Km2wBw4/Ab4RktoiSshgcgpJzC4keFPs6tLJS4IQwbeahxQS3E/w98uq6E1mirCH/id9xIXeQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/property-provider": "^4.2.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.42", + "resolved": "https://registry.npmmirror.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.42.tgz", + "integrity": "sha512-QDA84CWNe8Akpj15ofLO+1N3Rfg8qa2K5uX0y6HnOp4AnRYRgWrKx/xzbYNbVF9ZsyJUYOfcoaN3y93wA/QJ2A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/config-resolver": "^4.4.10", + "@smithy/credential-provider-imds": "^4.2.11", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-endpoints/-/util-endpoints-3.3.2.tgz", + "integrity": "sha512-+4HFLpE5u29AbFlTdlKIT7jfOzZ8PDYZKTb3e+AgLz986OYwqTourQ5H+jg79/66DB69Un1+qKecLnkZdAsYcA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz", + "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/util-middleware/-/util-middleware-4.2.11.tgz", + "integrity": "sha512-r3dtF9F+TpSZUxpOVVtPfk09Rlo4lT6ORBqEvX3IBT6SkQAdDSVKR5GcfmZbtl7WKhKnmb3wbDTQ6ibR2XHClw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/@smithy/util-retry/-/util-retry-4.2.11.tgz", + "integrity": "sha512-XSZULmL5x6aCTTii59wJqKsY1l3eMIAomRAccW7Tzh9r8s7T/7rdo03oektuH5jeYRlJMPcNP92EuRDvk9aXbw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/service-error-classification": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.5.17", + "resolved": "https://registry.npmmirror.com/@smithy/util-stream/-/util-stream-4.5.17.tgz", + "integrity": "sha512-793BYZ4h2JAQkNHcEnyFxDTcZbm9bVybD0UV/LEWmZ5bkTms7JqjfrLMi2Qy0E5WFcCzLwCAPgcvcvxoeALbAQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz", + "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.2.tgz", + "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@smithy/util-buffer-from": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@smithy/uuid/-/uuid-1.1.2.tgz", + "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@tinyhttp/content-disposition": { + "version": "2.2.4", + "resolved": "https://registry.npmmirror.com/@tinyhttp/content-disposition/-/content-disposition-2.2.4.tgz", + "integrity": "sha512-5Kc5CM2Ysn3vTTArBs2vESUt0AQiWZA86yc1TI3B+lxXmtEq133C1nxXNOgnzhrivdPZIh3zLj5gDnZjoLL5GA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.17.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tokenizer/inflate": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/@tokenizer/inflate/-/inflate-0.4.1.tgz", + "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.3", + "token-types": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT", + "peer": true + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmmirror.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/aws-lambda": { + "version": "8.10.161", + "resolved": "https://registry.npmmirror.com/@types/aws-lambda/-/aws-lambda-8.10.161.tgz", + "integrity": "sha512-rUYdp+MQwSFocxIOcSsYSF3YYYC/uUpMbCY/mbO21vGqfrEYvNSoPyKYDj6RhXXpPfS0KstW9RwG3qXh9sL7FQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bun": { + "version": "1.3.9", + "resolved": "https://registry.npmmirror.com/@types/bun/-/bun-1.3.9.tgz", + "integrity": "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "bun-types": "1.3.9" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmmirror.com/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://registry.npmmirror.com/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmmirror.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/mime-types": { + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/@types/mime-types/-/mime-types-2.1.4.tgz", + "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/node": { + "version": "25.3.5", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-25.3.5.tgz", + "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmmirror.com/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmmirror.com/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmmirror.com/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@whiskeysockets/baileys": { + "version": "7.0.0-rc.9", + "resolved": "https://registry.npmmirror.com/@whiskeysockets/baileys/-/baileys-7.0.0-rc.9.tgz", + "integrity": "sha512-YFm5gKXfDP9byCXCW3OPHKXLzrAKzolzgVUlRosHHgwbnf2YOO3XknkMm6J7+F0ns8OA0uuSBhgkRHTDtqkacw==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@cacheable/node-cache": "^1.4.0", + "@hapi/boom": "^9.1.3", + "async-mutex": "^0.5.0", + "libsignal": "git+https://github.com/whiskeysockets/libsignal-node.git", + "lru-cache": "^11.1.0", + "music-metadata": "^11.7.0", + "p-queue": "^9.0.0", + "pino": "^9.6", + "protobufjs": "^7.2.4", + "ws": "^8.13.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "audio-decode": "^2.1.3", + "jimp": "^1.6.0", + "link-preview-js": "^3.0.0", + "sharp": "*" + }, + "peerDependenciesMeta": { + "audio-decode": { + "optional": true + }, + "jimp": { + "optional": true + }, + "link-preview-js": { + "optional": true + } + } + }, + "node_modules/@whiskeysockets/baileys/node_modules/p-queue": { + "version": "9.1.0", + "resolved": "https://registry.npmmirror.com/p-queue/-/p-queue-9.1.0.tgz", + "integrity": "sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==", + "license": "MIT", + "peer": true, + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@whiskeysockets/baileys/node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "peer": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "peer": true, + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT", + "peer": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0", + "peer": true + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmmirror.com/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "license": "MIT", + "peer": true, + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT", + "peer": true + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/axios": { + "version": "1.13.6", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "peer": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/basic-ftp": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/basic-ftp/-/basic-ftp-5.2.0.tgz", + "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/before-after-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "peer": true, + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC", + "peer": true + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmmirror.com/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "license": "MIT", + "peer": true + }, + "node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmmirror.com/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "license": "MIT", + "peer": true + }, + "node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT", + "peer": true + }, + "node_modules/bun-types": { + "version": "1.3.9", + "resolved": "https://registry.npmmirror.com/bun-types/-/bun-types-1.3.9.tgz", + "integrity": "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/cacheable/-/cacheable-2.3.3.tgz", + "integrity": "sha512-iffYMX4zxKp54evOH27fm92hs+DeC1DhXmNVN8Tr94M/iZIV42dqTHSR2Ik4TOSPyOAwKr7Yu3rN9ALoLkbWyQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@cacheable/memory": "^2.0.8", + "@cacheable/utils": "^2.4.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.6.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chmodrp": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/chmodrp/-/chmodrp-1.0.2.tgz", + "integrity": "sha512-TdngOlFV1FLTzU0o1w8MB6/BFywhtLC0SzRTGJU7T9lmdjlCWeMRt1iVo0Ki+ldwNk0BqNiKoc8xpLZEQ8mY1w==", + "license": "MIT", + "peer": true + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "peer": true, + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmmirror.com/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "peer": true, + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmmirror.com/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "license": "ISC", + "peer": true, + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", + "peer": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cmake-js": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/cmake-js/-/cmake-js-8.0.0.tgz", + "integrity": "sha512-YbUP88RDwCvoQkZhRtGURYm9RIpWdtvZuhT87fKNoLjk8kIFIFeARpKfuZQGdwfH99GZpUmqSfcDrK62X7lTgg==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.3", + "fs-extra": "^11.3.3", + "node-api-headers": "^1.8.0", + "rc": "1.2.8", + "semver": "^7.7.3", + "tar": "^7.5.6", + "url-join": "^4.0.1", + "which": "^6.0.0", + "yargs": "^17.7.2" + }, + "bin": { + "cmake-js": "bin/cmake-js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT", + "peer": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "peer": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT", + "peer": true + }, + "node_modules/croner": { + "version": "10.0.1", + "resolved": "https://registry.npmmirror.com/croner/-/croner-10.0.1.tgz", + "integrity": "sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==", + "funding": [ + { + "type": "other", + "url": "https://paypal.me/hexagonpp" + }, + { + "type": "github", + "url": "https://github.com/sponsors/hexagon" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "peer": true + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "license": "MIT", + "peer": true + }, + "node_modules/curve25519-js": { + "version": "0.0.4", + "resolved": "https://registry.npmmirror.com/curve25519-js/-/curve25519-js-0.0.4.tgz", + "integrity": "sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==", + "license": "MIT", + "peer": true + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "8.0.3", + "resolved": "https://registry.npmmirror.com/diff/-/diff-8.0.3.tgz", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/discord-api-types": { + "version": "0.38.41", + "resolved": "https://registry.npmmirror.com/discord-api-types/-/discord-api-types-0.38.41.tgz", + "integrity": "sha512-yMECyR8j9c2fVTvCQ+Qc24pweYFIZk/XoxDOmt1UvPeSw5tK6gXBd/2hhP+FEAe9Y6ny8pRMaf618XDK4U53OQ==", + "license": "MIT", + "peer": true, + "workspaces": [ + "scripts/actions/documentation" + ] + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "peer": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause", + "peer": true + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "17.3.1", + "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-17.3.1.tgz", + "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT", + "peer": true + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT", + "peer": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "peer": true + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "peer": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-var": { + "version": "7.5.0", + "resolved": "https://registry.npmmirror.com/env-var/-/env-var-7.5.0.tgz", + "integrity": "sha512-mKZOzLRN0ETzau2W2QXefbFjo5EF4yWq28OyKb9ICdeNhHJlOE/pHHnz4hdYJ9cNZXcJHo5xN4OT4pzuSHSNvA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT", + "peer": true + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT", + "peer": true + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "peer": true, + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT", + "peer": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-content-type-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", + "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT", + "peer": true + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/fast-xml-builder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.0.0.tgz", + "integrity": "sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.1.tgz", + "integrity": "sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.0.0", + "strnum": "^2.1.2" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "peer": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-type": { + "version": "21.3.1", + "resolved": "https://registry.npmmirror.com/file-type/-/file-type-21.3.1.tgz", + "integrity": "sha512-SrzXX46I/zsRDjTb82eucsGg0ODq2NpGDp4HcsFKApPy8P8vACjpJRDoGGMfEzhFC0ry61ajd7f72J3603anBA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tokenizer/inflate": "^0.4.1", + "strtok3": "^10.3.4", + "token-types": "^6.1.1", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/filename-reserved-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", + "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/filenamify": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/filenamify/-/filenamify-6.0.0.tgz", + "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "filename-reserved-regex": "^3.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "peer": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmmirror.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "peer": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-extra": { + "version": "11.3.4", + "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmmirror.com/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmmirror.com/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "peer": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "peer": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "peer": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmmirror.com/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "license": "MIT", + "peer": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmmirror.com/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-auth-library": { + "version": "10.6.1", + "resolved": "https://registry.npmmirror.com/google-auth-library/-/google-auth-library-10.6.1.tgz", + "integrity": "sha512-5awwuLrzNol+pFDmKJd0dKtZ0fPLAtoA5p7YO4ODsDu6ONJUVqbYwvv8y2ZBO5MBNp9TJXigB19710kYpBPdtA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "7.1.3", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "peer": true + }, + "node_modules/grammy": { + "version": "1.41.1", + "resolved": "https://registry.npmmirror.com/grammy/-/grammy-1.41.1.tgz", + "integrity": "sha512-wcHAQ1e7svL3fJMpDchcQVcWUmywhuepOOjHUHmMmWAwUJEIyK5ea5sbSjZd+Gy1aMpZeP8VYJa+4tP+j1YptQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@grammyjs/types": "3.25.0", + "abort-controller": "^3.0.0", + "debug": "^4.4.3", + "node-fetch": "^2.7.0" + }, + "engines": { + "node": "^12.20.0 || >=14.13.1" + } + }, + "node_modules/grammy/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "peer": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "peer": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hashery": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/hashery/-/hashery-1.5.0.tgz", + "integrity": "sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "hookified": "^1.14.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/hono": { + "version": "4.12.5", + "resolved": "https://registry.npmmirror.com/hono/-/hono-4.12.5.tgz", + "integrity": "sha512-3qq+FUBtlTHhtYxbxheZgY8NIFnkkC/MR8u5TTsr7YZ3wixryQ3cCwn3iZbg8p8B88iDBBAYSfZDS75t8MN7Vg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmmirror.com/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "license": "MIT", + "peer": true + }, + "node_modules/hosted-git-info": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-9.0.2.tgz", + "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==", + "license": "ISC", + "peer": true, + "dependencies": { + "lru-cache": "^11.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT", + "peer": true + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT", + "peer": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC", + "peer": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC", + "peer": true + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/ipull": { + "version": "3.9.5", + "resolved": "https://registry.npmmirror.com/ipull/-/ipull-3.9.5.tgz", + "integrity": "sha512-5w/yZB5lXmTfsvNawmvkCjYo4SJNuKQz/av8TC1UiOyfOHyaM+DReqbpU2XpWYfmY+NIUbRRH8PUAWsxaS+IfA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tinyhttp/content-disposition": "^2.2.0", + "async-retry": "^1.3.3", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-spinners": "^2.9.2", + "commander": "^10.0.0", + "eventemitter3": "^5.0.1", + "filenamify": "^6.0.0", + "fs-extra": "^11.1.1", + "is-unicode-supported": "^2.0.0", + "lifecycle-utils": "^2.0.1", + "lodash.debounce": "^4.0.8", + "lowdb": "^7.0.1", + "pretty-bytes": "^6.1.0", + "pretty-ms": "^8.0.0", + "sleep-promise": "^9.1.0", + "slice-ansi": "^7.1.0", + "stdout-update": "^4.0.1", + "strip-ansi": "^7.1.0" + }, + "bin": { + "ipull": "dist/cli/cli.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/ido-pluto/ipull?sponsor=1" + }, + "optionalDependencies": { + "@reflink/reflink": "^0.1.16" + } + }, + "node_modules/ipull/node_modules/lifecycle-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/lifecycle-utils/-/lifecycle-utils-2.1.0.tgz", + "integrity": "sha512-AnrXnE2/OF9PHCyFg0RSqsnQTzV991XaZA/buhFDoc58xU7rhSCDgCz/09Lqpsn4MpoPHt7TRAXV1kWZypFVsA==", + "license": "MIT", + "peer": true + }, + "node_modules/ipull/node_modules/parse-ms": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-3.0.0.tgz", + "integrity": "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ipull/node_modules/pretty-ms": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/pretty-ms/-/pretty-ms-8.0.0.tgz", + "integrity": "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "parse-ms": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ipull/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/is-electron": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==", + "license": "MIT", + "peer": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT", + "peer": true + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", + "peer": true + }, + "node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": ">=20" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "license": "MIT", + "peer": true, + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT", + "peer": true + }, + "node_modules/json-with-bigint": { + "version": "3.5.7", + "resolved": "https://registry.npmmirror.com/json-with-bigint/-/json-with-bigint-3.5.7.tgz", + "integrity": "sha512-7ei3MdAI5+fJPVnKlW77TKNKwQ5ppSzWvhPuSuINT/GYW9ZOC1eRKOuhV9yHG5aEsUPj9BBx5JIekkmoLHxZOw==", + "license": "MIT", + "peer": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "peer": true, + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "peer": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "peer": true, + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmmirror.com/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/koffi": { + "version": "2.15.1", + "resolved": "https://registry.npmmirror.com/koffi/-/koffi-2.15.1.tgz", + "integrity": "sha512-mnc0C0crx/xMSljb5s9QbnLrlFHprioFO1hkXyuSuO/QtbpLDa0l/uM21944UfQunMKmp3/r789DTDxVyyH6aA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, + "funding": { + "url": "https://liberapay.com/Koromix" + } + }, + "node_modules/libsignal": { + "name": "@whiskeysockets/libsignal-node", + "version": "2.0.1", + "resolved": "git+ssh://git@github.com/whiskeysockets/libsignal-node.git#1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67", + "license": "GPL-3.0", + "peer": true, + "dependencies": { + "curve25519-js": "^0.0.4", + "protobufjs": "6.8.8" + } + }, + "node_modules/libsignal/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "license": "MIT", + "peer": true + }, + "node_modules/libsignal/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/libsignal/node_modules/protobufjs": { + "version": "6.8.8", + "resolved": "https://registry.npmmirror.com/protobufjs/-/protobufjs-6.8.8.tgz", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lifecycle-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/lifecycle-utils/-/lifecycle-utils-3.1.1.tgz", + "integrity": "sha512-gNd3OvhFNjHykJE3uGntz7UuPzWlK9phrIdXxU9Adis0+ExkwnZibfxCJWiWWZ+a6VbKiZrb+9D9hCQWd4vjTg==", + "license": "MIT", + "peer": true + }, + "node_modules/linkedom": { + "version": "0.18.12", + "resolved": "https://registry.npmmirror.com/linkedom/-/linkedom-0.18.12.tgz", + "integrity": "sha512-jalJsOwIKuQJSeTvsgzPe9iJzyfVaEJiEXl+25EkKevsULHvMJzpNqwvj1jOESWdmgKDiXObyjOYwlUqG7wo1Q==", + "license": "ISC", + "peer": true, + "dependencies": { + "css-select": "^5.1.0", + "cssom": "^0.5.0", + "html-escaper": "^3.0.3", + "htmlparser2": "^10.0.0", + "uhyphen": "^0.2.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "canvas": ">= 2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.identity": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/lodash.identity/-/lodash.identity-3.0.0.tgz", + "integrity": "sha512-AupTIzdLQxJS5wIYUQlgGyk2XRTfGXA+MCghDHqZk0pzUNYvd3EESS6dkChNauNYVIutcb0dfHw1ri9Q1yPV8Q==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.pickby": { + "version": "4.6.0", + "resolved": "https://registry.npmmirror.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz", + "integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==", + "license": "MIT", + "peer": true + }, + "node_modules/log-symbols": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-7.0.1.tgz", + "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", + "license": "MIT", + "peer": true, + "dependencies": { + "is-unicode-supported": "^2.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/lowdb": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/lowdb/-/lowdb-7.0.1.tgz", + "integrity": "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==", + "license": "MIT", + "peer": true, + "dependencies": { + "steno": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/marked": { + "version": "15.0.12", + "resolved": "https://registry.npmmirror.com/marked/-/marked-15.0.12.tgz", + "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", + "license": "MIT", + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT", + "peer": true + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "peer": true, + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/music-metadata": { + "version": "11.12.1", + "resolved": "https://registry.npmmirror.com/music-metadata/-/music-metadata-11.12.1.tgz", + "integrity": "sha512-j++ltLxHDb5VCXET9FzQ8bnueiLHwQKgCO7vcbkRH/3F7fRjPkv6qncGEJ47yFhmemcYtgvsOAlcQ1dRBTkDjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + }, + { + "type": "buymeacoffee", + "url": "https://buymeacoffee.com/borewit" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@borewit/text-codec": "^0.2.1", + "@tokenizer/token": "^0.3.0", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "file-type": "^21.3.0", + "media-typer": "^1.1.0", + "strtok3": "^10.3.4", + "token-types": "^6.1.2", + "uint8array-extras": "^1.5.0", + "win-guid": "^0.2.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "5.1.6", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.1.6.tgz", + "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-addon-api": { + "version": "8.6.0", + "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-8.6.0.tgz", + "integrity": "sha512-gBVjCaqDlRUk0EwoPNKzIr9KkS9041G/q31IBShPs1Xz6UTA+EXdZADbzqAJQrpDRq71CIMnOP5VMut3SL0z5Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-api-headers": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/node-api-headers/-/node-api-headers-1.8.0.tgz", + "integrity": "sha512-jfnmiKWjRAGbdD1yQS28bknFM1tbHC1oucyuMPjmkEs+kpiu76aRs40WlTmBmyEgzDM76ge1DQ7XJ3R5deiVjQ==", + "license": "MIT", + "peer": true + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-edge-tts": { + "version": "1.2.10", + "resolved": "https://registry.npmmirror.com/node-edge-tts/-/node-edge-tts-1.2.10.tgz", + "integrity": "sha512-bV2i4XU54D45+US0Zm1HcJRkifuB3W438dWyuJEHLQdKxnuqlI1kim2MOvR6Q3XUQZvfF9PoDyR1Rt7aeXhPdQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "https-proxy-agent": "^7.0.1", + "ws": "^8.13.0", + "yargs": "^17.7.2" + }, + "bin": { + "node-edge-tts": "bin.js" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "peer": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-llama-cpp": { + "version": "3.16.2", + "resolved": "https://registry.npmmirror.com/node-llama-cpp/-/node-llama-cpp-3.16.2.tgz", + "integrity": "sha512-ovhuTaXSWfcoyfI8ljWxO2Rg63mNxqQQAbDGkXRhlgsL7UjPqm2Nsy1bTNa0ZaQRg3vezG4agnCJTImrICY/0A==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@huggingface/jinja": "^0.5.5", + "async-retry": "^1.3.3", + "bytes": "^3.1.2", + "chalk": "^5.6.2", + "chmodrp": "^1.0.2", + "cmake-js": "^8.0.0", + "cross-spawn": "^7.0.6", + "env-var": "^7.5.0", + "filenamify": "^6.0.0", + "fs-extra": "^11.3.0", + "ignore": "^7.0.4", + "ipull": "^3.9.5", + "is-unicode-supported": "^2.1.0", + "lifecycle-utils": "^3.1.1", + "log-symbols": "^7.0.1", + "nanoid": "^5.1.6", + "node-addon-api": "^8.5.0", + "octokit": "^5.0.5", + "ora": "^9.3.0", + "pretty-ms": "^9.3.0", + "proper-lockfile": "^4.1.2", + "semver": "^7.7.1", + "simple-git": "^3.31.1", + "slice-ansi": "^8.0.0", + "stdout-update": "^4.0.1", + "strip-ansi": "^7.1.2", + "validate-npm-package-name": "^7.0.2", + "which": "^6.0.1", + "yargs": "^17.7.2" + }, + "bin": { + "nlc": "dist/cli/cli.js", + "node-llama-cpp": "dist/cli/cli.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/giladgd" + }, + "optionalDependencies": { + "@node-llama-cpp/linux-arm64": "3.16.2", + "@node-llama-cpp/linux-armv7l": "3.16.2", + "@node-llama-cpp/linux-x64": "3.16.2", + "@node-llama-cpp/linux-x64-cuda": "3.16.2", + "@node-llama-cpp/linux-x64-cuda-ext": "3.16.2", + "@node-llama-cpp/linux-x64-vulkan": "3.16.2", + "@node-llama-cpp/mac-arm64-metal": "3.16.2", + "@node-llama-cpp/mac-x64": "3.16.2", + "@node-llama-cpp/win-arm64": "3.16.2", + "@node-llama-cpp/win-x64": "3.16.2", + "@node-llama-cpp/win-x64-cuda": "3.16.2", + "@node-llama-cpp/win-x64-cuda-ext": "3.16.2", + "@node-llama-cpp/win-x64-vulkan": "3.16.2" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/node-llama-cpp/node_modules/@node-llama-cpp/linux-x64-cuda": { + "optional": true, + "peer": true + }, + "node_modules/node-llama-cpp/node_modules/@node-llama-cpp/linux-x64-cuda-ext": { + "optional": true, + "peer": true + }, + "node_modules/node-llama-cpp/node_modules/@node-llama-cpp/win-x64-cuda": { + "optional": true, + "peer": true + }, + "node_modules/node-llama-cpp/node_modules/@node-llama-cpp/win-x64-cuda-ext": { + "optional": true, + "peer": true + }, + "node_modules/node-llama-cpp/node_modules/@node-llama-cpp/win-x64-vulkan": { + "optional": true, + "peer": true + }, + "node_modules/node-readable-to-web-readable-stream": { + "version": "0.4.2", + "resolved": "https://registry.npmmirror.com/node-readable-to-web-readable-stream/-/node-readable-to-web-readable-stream-0.4.2.tgz", + "integrity": "sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/octokit": { + "version": "5.0.5", + "resolved": "https://registry.npmmirror.com/octokit/-/octokit-5.0.5.tgz", + "integrity": "sha512-4+/OFSqOjoyULo7eN7EA97DE0Xydj/PW5aIckxqQIoFjFwqXKuFCvXUJObyJfBF9Khu4RL/jlDRI9FPaMGfPnw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/app": "^16.1.2", + "@octokit/core": "^7.0.6", + "@octokit/oauth-app": "^8.0.3", + "@octokit/plugin-paginate-graphql": "^6.0.0", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/plugin-rest-endpoint-methods": "^17.0.0", + "@octokit/plugin-retry": "^8.0.3", + "@octokit/plugin-throttling": "^11.0.3", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "@octokit/webhooks": "^14.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openai": { + "version": "6.26.0", + "resolved": "https://registry.npmmirror.com/openai/-/openai-6.26.0.tgz", + "integrity": "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/openclaw": { + "version": "2026.3.8", + "resolved": "https://registry.npmmirror.com/openclaw/-/openclaw-2026.3.8.tgz", + "integrity": "sha512-e5Rk2Aj55sD/5LyX94mdYCQj7zpHXo0xIZsl+k140+nRopePfPAxC7nsu0V/NyypPRtaotP1riFfzK7IhaYkuQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@agentclientprotocol/sdk": "0.15.0", + "@aws-sdk/client-bedrock": "^3.1004.0", + "@buape/carbon": "0.0.0-beta-20260216184201", + "@clack/prompts": "^1.1.0", + "@discordjs/voice": "^0.19.0", + "@grammyjs/runner": "^2.0.3", + "@grammyjs/transformer-throttler": "^1.2.1", + "@homebridge/ciao": "^1.3.5", + "@larksuiteoapi/node-sdk": "^1.59.0", + "@line/bot-sdk": "^10.6.0", + "@lydell/node-pty": "1.2.0-beta.3", + "@mariozechner/pi-agent-core": "0.57.1", + "@mariozechner/pi-ai": "0.57.1", + "@mariozechner/pi-coding-agent": "0.57.1", + "@mariozechner/pi-tui": "0.57.1", + "@mozilla/readability": "^0.6.0", + "@sinclair/typebox": "0.34.48", + "@slack/bolt": "^4.6.0", + "@slack/web-api": "^7.14.1", + "@whiskeysockets/baileys": "7.0.0-rc.9", + "ajv": "^8.18.0", + "chalk": "^5.6.2", + "chokidar": "^5.0.0", + "cli-highlight": "^2.1.11", + "commander": "^14.0.3", + "croner": "^10.0.1", + "discord-api-types": "^0.38.41", + "dotenv": "^17.3.1", + "express": "^5.2.1", + "file-type": "^21.3.0", + "grammy": "^1.41.1", + "https-proxy-agent": "^7.0.6", + "ipaddr.js": "^2.3.0", + "jiti": "^2.6.1", + "json5": "^2.2.3", + "jszip": "^3.10.1", + "linkedom": "^0.18.12", + "long": "^5.3.2", + "markdown-it": "^14.1.1", + "node-edge-tts": "^1.2.10", + "opusscript": "^0.1.1", + "osc-progress": "^0.3.0", + "pdfjs-dist": "^5.5.207", + "playwright-core": "1.58.2", + "qrcode-terminal": "^0.12.0", + "sharp": "^0.34.5", + "sqlite-vec": "0.1.7-alpha.2", + "tar": "7.5.11", + "tslog": "^4.10.2", + "undici": "^7.22.0", + "ws": "^8.19.0", + "yaml": "^2.8.2", + "zod": "^4.3.6" + }, + "bin": { + "openclaw": "openclaw.mjs" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "@napi-rs/canvas": "^0.1.89", + "node-llama-cpp": "3.16.2" + } + }, + "node_modules/openclaw/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=20" + } + }, + "node_modules/opusscript": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/opusscript/-/opusscript-0.1.1.tgz", + "integrity": "sha512-mL0fZZOUnXdZ78woRXp18lApwpp0lF5tozJOD1Wut0dgrA9WuQTgSels/CSmFleaAZrJi/nci5KOVtbuxeWoQA==", + "license": "MIT", + "peer": true + }, + "node_modules/ora": { + "version": "9.3.0", + "resolved": "https://registry.npmmirror.com/ora/-/ora-9.3.0.tgz", + "integrity": "sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw==", + "license": "MIT", + "peer": true, + "dependencies": { + "chalk": "^5.6.2", + "cli-cursor": "^5.0.0", + "cli-spinners": "^3.2.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.1.0", + "log-symbols": "^7.0.1", + "stdin-discarder": "^0.3.1", + "string-width": "^8.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/cli-spinners": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-3.4.0.tgz", + "integrity": "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/osc-progress": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/osc-progress/-/osc-progress-0.3.0.tgz", + "integrity": "sha512-4/8JfsetakdeEa4vAYV45FW20aY+B/+K8NEXp5Eiar3wR8726whgHrbSg5Ar/ZY1FLJ/AGtUqV7W2IVF+Gvp9A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=20" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmmirror.com/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT", + "peer": true + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", + "peer": true, + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0", + "peer": true + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)", + "peer": true + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "license": "MIT", + "peer": true + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "license": "MIT", + "peer": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "license": "MIT", + "peer": true + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/partial-json": { + "version": "0.1.7", + "resolved": "https://registry.npmmirror.com/partial-json/-/partial-json-0.1.7.tgz", + "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", + "license": "MIT", + "peer": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pdfjs-dist": { + "version": "5.5.207", + "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-5.5.207.tgz", + "integrity": "sha512-WMqqw06w1vUt9ZfT0gOFhMf3wHsWhaCrxGrckGs5Cci6ybDW87IvPaOd2pnBwT6BJuP/CzXDZxjFgmSULLdsdw==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=20.19.0 || >=22.13.0 || >=24" + }, + "optionalDependencies": { + "@napi-rs/canvas": "^0.1.95", + "node-readable-to-web-readable-stream": "^0.4.2" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT", + "peer": true + }, + "node_modules/pino": { + "version": "9.14.0", + "resolved": "https://registry.npmmirror.com/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT", + "peer": true + }, + "node_modules/playwright-core": { + "version": "1.58.2", + "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/pretty-bytes": { + "version": "6.1.1", + "resolved": "https://registry.npmmirror.com/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmmirror.com/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT", + "peer": true + }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/proper-lockfile/node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmmirror.com/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmmirror.com/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "peer": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT", + "peer": true + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "peer": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qified": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/qified/-/qified-0.6.0.tgz", + "integrity": "sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==", + "license": "MIT", + "peer": true, + "dependencies": { + "hookified": "^1.14.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/qrcode-terminal": { + "version": "0.12.0", + "resolved": "https://registry.npmmirror.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT", + "peer": true + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "peer": true, + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "peer": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", + "peer": true + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", + "peer": true, + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmmirror.com/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT", + "peer": true + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "peer": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC", + "peer": true + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT", + "peer": true + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "peer": true, + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT", + "peer": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC", + "peer": true + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmmirror.com/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "peer": true + }, + "node_modules/simple-git": { + "version": "3.32.3", + "resolved": "https://registry.npmmirror.com/simple-git/-/simple-git-3.32.3.tgz", + "integrity": "sha512-56a5oxFdWlsGygOXHWrG+xjj5w9ZIt2uQbzqiIGdR/6i5iococ7WQ/bNPzWxCJdEUGUCmyMH0t9zMpRJTaKxmw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT", + "peer": true + }, + "node_modules/sleep-promise": { + "version": "9.1.0", + "resolved": "https://registry.npmmirror.com/sleep-promise/-/sleep-promise-9.1.0.tgz", + "integrity": "sha512-UHYzVpz9Xn8b+jikYSD6bqvf754xL2uBUzDFwiU6NcdZeifPr6UfgU43xpkPu67VMS88+TI2PSI7Eohgqf2fKA==", + "license": "MIT", + "peer": true + }, + "node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmmirror.com/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmmirror.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sqlite-vec": { + "version": "0.1.7-alpha.2", + "resolved": "https://registry.npmmirror.com/sqlite-vec/-/sqlite-vec-0.1.7-alpha.2.tgz", + "integrity": "sha512-rNgRCv+4V4Ed3yc33Qr+nNmjhtrMnnHzXfLVPeGb28Dx5mmDL3Ngw/Wk8vhCGjj76+oC6gnkmMG8y73BZWGBwQ==", + "license": "MIT OR Apache", + "peer": true, + "optionalDependencies": { + "sqlite-vec-darwin-arm64": "0.1.7-alpha.2", + "sqlite-vec-darwin-x64": "0.1.7-alpha.2", + "sqlite-vec-linux-arm64": "0.1.7-alpha.2", + "sqlite-vec-linux-x64": "0.1.7-alpha.2", + "sqlite-vec-windows-x64": "0.1.7-alpha.2" + } + }, + "node_modules/sqlite-vec-darwin-arm64": { + "version": "0.1.7-alpha.2", + "resolved": "https://registry.npmmirror.com/sqlite-vec-darwin-arm64/-/sqlite-vec-darwin-arm64-0.1.7-alpha.2.tgz", + "integrity": "sha512-raIATOqFYkeCHhb/t3r7W7Cf2lVYdf4J3ogJ6GFc8PQEgHCPEsi+bYnm2JT84MzLfTlSTIdxr4/NKv+zF7oLPw==", + "cpu": [ + "arm64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/sqlite-vec-darwin-x64": { + "version": "0.1.7-alpha.2", + "resolved": "https://registry.npmmirror.com/sqlite-vec-darwin-x64/-/sqlite-vec-darwin-x64-0.1.7-alpha.2.tgz", + "integrity": "sha512-jeZEELsQjjRsVojsvU5iKxOvkaVuE+JYC8Y4Ma8U45aAERrDYmqZoHvgSG7cg1PXL3bMlumFTAmHynf1y4pOzA==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/sqlite-vec-linux-arm64": { + "version": "0.1.7-alpha.2", + "resolved": "https://registry.npmmirror.com/sqlite-vec-linux-arm64/-/sqlite-vec-linux-arm64-0.1.7-alpha.2.tgz", + "integrity": "sha512-6Spj4Nfi7tG13jsUG+W7jnT0bCTWbyPImu2M8nWp20fNrd1SZ4g3CSlDAK8GBdavX7wRlbBHCZ+BDa++rbDewA==", + "cpu": [ + "arm64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/sqlite-vec-linux-x64": { + "version": "0.1.7-alpha.2", + "resolved": "https://registry.npmmirror.com/sqlite-vec-linux-x64/-/sqlite-vec-linux-x64-0.1.7-alpha.2.tgz", + "integrity": "sha512-IcgrbHaDccTVhXDf8Orwdc2+hgDLAFORl6OBUhcvlmwswwBP1hqBTSEhovClG4NItwTOBNgpwOoQ7Qp3VDPWLg==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/sqlite-vec-windows-x64": { + "version": "0.1.7-alpha.2", + "resolved": "https://registry.npmmirror.com/sqlite-vec-windows-x64/-/sqlite-vec-windows-x64-0.1.7-alpha.2.tgz", + "integrity": "sha512-TRP6hTjAcwvQ6xpCZvjP00pdlda8J38ArFy1lMYhtQWXiIBmWnhMaMbq4kaeCYwvTTddfidatRS+TJrwIKB/oQ==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "license": "MIT", + "peer": true + }, + "node_modules/stdin-discarder": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.3.1.tgz", + "integrity": "sha512-reExS1kSGoElkextOcPkel4NE99S0BWxjUHQeDFnR8S993JxpPX7KU4MNmO19NXhlJp+8dmdCbKQVNgLJh2teA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stdout-update": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/stdout-update/-/stdout-update-4.0.1.tgz", + "integrity": "sha512-wiS21Jthlvl1to+oorePvcyrIkiG/6M3D3VTmDUlJm7Cy6SbFhKkAvX+YBuHLxck/tO3mrdpC/cNesigQc3+UQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "ansi-styles": "^6.2.1", + "string-width": "^7.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/stdout-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT", + "peer": true + }, + "node_modules/stdout-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/steno": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/steno/-/steno-4.0.2.tgz", + "integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", + "peer": true + }, + "node_modules/string-width": { + "version": "8.2.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-8.2.0.tgz", + "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", + "license": "MIT", + "peer": true, + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "2.1.2", + "resolved": "https://mirrors.tencent.com/npm/strnum/-/strnum-2.1.2.tgz", + "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/strtok3": { + "version": "10.3.4", + "resolved": "https://registry.npmmirror.com/strtok3/-/strtok3-10.3.4.tgz", + "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tokenizer/token": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "7.5.11", + "resolved": "https://registry.npmmirror.com/tar/-/tar-7.5.11.tgz", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "peer": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "peer": true, + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/toad-cache": { + "version": "3.7.0", + "resolved": "https://registry.npmmirror.com/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", + "license": "MIT", + "peer": true, + "dependencies": { + "@borewit/text-codec": "^0.2.1", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", + "peer": true + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT", + "peer": true + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "peer": true + }, + "node_modules/tslog": { + "version": "4.10.2", + "resolved": "https://registry.npmmirror.com/tslog/-/tslog-4.10.2.tgz", + "integrity": "sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/fullstack-build/tslog?sponsor=1" + } + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "peer": true, + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT", + "peer": true + }, + "node_modules/uhyphen": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/uhyphen/-/uhyphen-0.2.0.tgz", + "integrity": "sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==", + "license": "ISC", + "peer": true + }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici": { + "version": "7.22.0", + "resolved": "https://mirrors.tencent.com/npm/undici/-/undici-7.22.0.tgz", + "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "license": "MIT", + "peer": true + }, + "node_modules/universal-github-app-jwt": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/universal-github-app-jwt/-/universal-github-app-jwt-2.2.2.tgz", + "integrity": "sha512-dcmbeSrOdTnsjGjUfAlqNDJrhxXizjAz94ija9Qw8YkZ1uu0d+GoZzyH+Jb9tIIqvGsadUfwg+22k5aDqqwzbw==", + "license": "MIT", + "peer": true + }, + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "license": "MIT", + "peer": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT", + "peer": true + }, + "node_modules/validate-npm-package-name": { + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", + "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", + "license": "ISC", + "peer": true, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", + "peer": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "peer": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/win-guid": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/win-guid/-/win-guid-0.2.1.tgz", + "integrity": "sha512-gEIQU4mkgl2OPeoNrWflcJFJ3Ae2BPd4eCsHHA/XikslkIVms/nHhvnvzIZV7VLmBvtFlDOzLt9rrZT+n6D67A==", + "license": "MIT", + "peer": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC", + "peer": true + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://mirrors.tencent.com/npm/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmmirror.com/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://mirrors.tencent.com/npm/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.1", + "resolved": "https://registry.npmmirror.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", + "license": "ISC", + "peer": true, + "peerDependencies": { + "zod": "^3.25 || ^4" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..72fd1ef --- /dev/null +++ b/package.json @@ -0,0 +1,44 @@ +{ + "name": "wechat-access", + "version": "1.0.0", + "type": "module", + "description": "简化的企业微信 服务号 接收消息 Demo", + "author": "aa", + "openclaw": { + "extensions": [ + "./index.ts" + ], + "channel": { + "id": "wechat-access", + "label": "wechat-access", + "selectionLabel": "WeCom (plugin)", + "detailLabel": "WeCom Bot", + "docsPath": "/channels/wechat-access", + "docsLabel": "wechat-access", + "blurb": "Enterprise WeCom intelligent bot (API mode) via encrypted webhooks + passive replies.", + "aliases": [ + "wechatwork", + "wework", + "服务号", + "企微", + "企业微信" + ], + "order": 85 + }, + "install": { + "npmSpec": "@yanhaidao/wechat-access", + "localPath": "extensions/wechat-access", + "defaultChoice": "npm" + } + }, + "dependencies": { + "fast-xml-parser": "^5.4.1", + "qrcode-terminal": "^0.12.0", + "undici": "^7.20.0", + "ws": "^8.18.0", + "zod": "^4.3.6" + }, + "peerDependencies": { + "openclaw": ">=2026.1.26" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..be10441 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./dist", + "rootDir": "./", + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": [ + "index.ts", + "http/**/*.ts", + "websocket/**/*.ts", + "auth/**/*.ts", + "common/**/*.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] +} \ No newline at end of file diff --git a/websocket.md b/websocket.md new file mode 100644 index 0000000..92030d2 --- /dev/null +++ b/websocket.md @@ -0,0 +1,273 @@ +agentwsserver WebSocket 接口文档 +目录 +1.概述 +2.连接 +3.数据协议 (AGP Envelope) +4.下行消息 (服务端 → 客户端) +5.上行消息 (客户端 → 服务端) +6.通用数据结构 +7.时序示意 + +概述 +为独立 APP 提供 WebSocket 双向通信能力。 +WebSocket 服务 — 运行于 :8080 端口,处理客户端的 WebSocket 长连接 +数据协议 — 使用 AGP (Agent Gateway Protocol) 统一消息信封 +消息传输 — 所有消息均为 WebSocket Text 帧,内容为 JSON + +连接 +地址 +ws://21.0.62.97:8080/?token={token} +Query 参数 +参数 类型 必填 说明 +token string 否 鉴权 token(当前未校验,后续启用) +连接行为 +握手成功后服务端注册连接,同一 guid 的旧连接会被踢下线 +空闲超时 5 分钟,超时无消息收发将断开 +连接断开后服务端自动清理路由注册 +错误场景 +场景 行为 +缺少 guid 或 user_id 握手拒绝,WebSocket 连接不会建立 +URL 解析失败 握手拒绝 + +数据协议 (AGP Envelope) +Envelope 结构 +所有 WebSocket 消息(上行和下行)均使用统一的 AGP 信封格式: +{ +"msg_id": "string", +"guid": "string", +"user_id": "string", +"method": "string", +"payload": {} +} +字段 类型 必填 说明 +msg_id string 是 全局唯一消息 ID(UUID),用于幂等去重 +guid string 是 设备 GUID +user_id string 是 用户账户 ID +method string 是 消息类型,见下方枚举 +payload object 是 消息载荷(JSON 对象,根据 method 类型而异) +Method 枚举 +method 方向 说明 +session.prompt 服务端 → 客户端 下发用户指令 +session.cancel 服务端 → 客户端 取消 Prompt Turn +session.update 客户端 → 服务端 流式中间更新 +session.promptResponse 客户端 → 服务端 最终结果 + +下行消息 (服务端 → 客户端) +session.prompt — 下发用户指令 +{ +"msg_id": "550e8400-e29b-41d4-a716-446655440000", +"guid": "device_001", +"user_id": "user_123", +"method": "session.prompt", +"payload": { +"session_id": "550e8400-e29b-41d4-a716-446655440000", +"prompt_id": "550e8400-e29b-41d4-a716-446655440001", +"agent_app": "openclaw", +"content": [ +{ "type": "text", "text": "帮我查一下今天的天气" } +] +} +} +payload 字段: +字段 类型 必填 说明 +session_id string 是 所属 Session ID +prompt_id string 是 本次 Turn 唯一 ID +agent_app string 是 目标 AI 应用标识,客户端据此路由到本地 AI 应用 +content ContentBlock[] 是 用户指令内容(数组) +session.cancel — 取消 Prompt Turn +{ +"msg_id": "550e8400-e29b-41d4-a716-446655440001", +"guid": "device_001", +"user_id": "user_123", +"method": "session.cancel", +"payload": { +"session_id": "550e8400-e29b-41d4-a716-446655440000", +"prompt_id": "550e8400-e29b-41d4-a716-446655440001", +"agent_app": "openclaw" +} +} +payload 字段: +字段 类型 必填 说明 +session_id string 是 所属 Session ID +prompt_id string 是 要取消的 Turn ID +agent_app string 是 目标 AI 应用标识 + +上行消息 (客户端 → 服务端) +session.update — 流式中间更新 +客户端在处理 session.prompt 期间,通过此消息上报中间进度。可多次发送。 +update_type 枚举 +update_type 说明 使用字段 +message_chunk 增量文本/内容(Agent 消息片段) content +tool_call AI 正在调用工具 tool_call +tool_call_update 工具执行状态变更 tool_call +payload 字段 +字段 类型 必填 说明 +session_id string 是 所属 Session ID +prompt_id string 是 所属 Turn ID +update_type string 是 更新类型,取值见上方枚举 +content ContentBlock 条件 update_type=message_chunk 时使用,单个对象(非数组) +tool_call ToolCall 条件 update_type=tool_call 或 tool_call_update 时使用 +注意: content 字段为单个 ContentBlock 对象,不是数组。与 session.promptResponse 的 content 数组不同。 +示例 — message_chunk(增量文本) +{ +"msg_id": "550e8400-e29b-41d4-a716-446655440002", +"guid": "device_001", +"user_id": "user_123", +"method": "session.update", +"payload": { +"session_id": "550e8400-e29b-41d4-a716-446655440000", +"prompt_id": "550e8400-e29b-41d4-a716-446655440001", +"update_type": "message_chunk", +"content": { +"type": "text", +"text": "正在思考中...第一步是..." +} +} +} +示例 — tool_call(工具调用) +{ +"msg_id": "550e8400-e29b-41d4-a716-446655440003", +"guid": "device_001", +"user_id": "user_123", +"method": "session.update", +"payload": { +"session_id": "550e8400-e29b-41d4-a716-446655440000", +"prompt_id": "550e8400-e29b-41d4-a716-446655440001", +"update_type": "tool_call", +"tool_call": { +"tool_call_id": "tc-001", +"title": "扫描临时文件", +"kind": "execute", +"status": "pending" +} +} +} +示例 — tool_call_update(工具状态更新) +{ +"msg_id": "550e8400-e29b-41d4-a716-446655440004", +"guid": "device_001", +"user_id": "user_123", +"method": "session.update", +"payload": { +"session_id": "550e8400-e29b-41d4-a716-446655440000", +"prompt_id": "550e8400-e29b-41d4-a716-446655440001", +"update_type": "tool_call_update", +"tool_call": { +"tool_call_id": "tc-001", +"status": "completed", +"content": [{ "type": "text", "text": "发现临时文件 2.3GB" }] +} +} +} + +session.promptResponse — 最终结果 +客户端完成 session.prompt 处理后,上报最终结果。每个 prompt_id 只接受一次最终响应,重复的 msg_id 会被去重。 +{ +"msg_id": "550e8400-e29b-41d4-a716-446655440005", +"guid": "device_001", +"user_id": "user_123", +"method": "session.promptResponse", +"payload": { +"session_id": "550e8400-e29b-41d4-a716-446655440000", +"prompt_id": "550e8400-e29b-41d4-a716-446655440001", +"stop_reason": "end_turn", +"content": [ +{ "type": "text", "text": "今天北京晴,气温 15°C" } +] +} +} +payload 字段: +字段 类型 必填 说明 +session_id string 是 所属 Session ID +prompt_id string 是 所属 Turn ID +stop_reason string 是 停止原因 +content ContentBlock[] 否 最终结果内容(数组) +error string 否 错误描述(stop_reason 为 error / refusal 时附带) +stop_reason 枚举: +值 说明 +end_turn 正常完成 +cancelled 被取消 +refusal AI 应用拒绝执行 +error 技术错误 +错误响应示例 +{ +"msg_id": "550e8400-e29b-41d4-a716-446655440006", +"guid": "device_001", +"user_id": "user_123", +"method": "session.promptResponse", +"payload": { +"session_id": "550e8400-e29b-41d4-a716-446655440000", +"prompt_id": "550e8400-e29b-41d4-a716-446655440001", +"stop_reason": "error", +"error": "AI 应用执行超时" +} +} + +通用数据结构 +ContentBlock — 内容块 +{ +"type": "text", +"text": "文本内容" +} +字段 类型 必填 说明 +type string 是 内容类型,当前仅支持 "text" +text string 是 type=text 时必填 +ToolCall — 工具调用 +{ +"tool_call_id": "tc-001", +"title": "扫描临时文件", +"kind": "execute", +"status": "in_progress", +"content": [{ "type": "text", "text": "发现临时文件 2.3GB" }], +"locations": [{ "path": "/tmp" }] +} +字段 类型 必填 说明 +tool_call_id string 是 工具调用唯一 ID +title string 否 工具调用标题(展示用) +kind string 否 工具类型 +status string 是 工具调用状态 +content ContentBlock[] 否 工具调用结果内容 +locations Location[] 否 工具操作路径 +kind 枚举: +值 说明 +read 读取 +edit 编辑 +delete 删除 +execute 执行 +search 搜索 +fetch 获取 +think 思考 +other 其他 +status 枚举: +值 说明 +pending 等待中 +in_progress 执行中 +completed 已完成 +failed 失败 +Location — 路径 +{ "path": "/tmp" } +字段 类型 说明 +path string 操作路径 + +时序示意 +正常流程 +客户端 (APP) 服务端 +| | +|--- WS 握手 (guid/user_id) ----->| +|<-- 101 Switching Protocols -----| 连接建立 +| | +|<-- session.prompt (WS Text) ----| 下发指令 +| | +|--- session.update (WS Text) --->| 流式上报(可多次) +|--- session.update (WS Text) --->| +| | +|--- promptResponse (WS Text) --->| 最终结果 +| | +|--- 断开 / 超时 ---------------->| 连接清理 +取消流程 +客户端 (APP) 服务端 +| | +| (正在处理 session.prompt) | +|<-- session.cancel (WS Text) ----| 服务端取消 +| | +|--- promptResponse (WS Text) --->| stop_reason: "cancelled" \ No newline at end of file diff --git a/websocket/index.ts b/websocket/index.ts new file mode 100644 index 0000000..e85a1fa --- /dev/null +++ b/websocket/index.ts @@ -0,0 +1,40 @@ +// ============================================ +// WebSocket 模块导出 +// ============================================ + +// 类型定义 +export type { + AGPEnvelope, + AGPMethod, + ContentBlock, + ToolCall, + ToolCallKind, + ToolCallStatus, + ToolLocation, + PromptPayload, + CancelPayload, + UpdatePayload, + UpdateType, + PromptResponsePayload, + StopReason, + PromptMessage, + CancelMessage, + UpdateMessage, + PromptResponseMessage, + WebSocketClientConfig, + ConnectionState, + WebSocketClientCallbacks, +} from "./types.js"; + +// WebSocket 客户端 +export { WechatAccessWebSocketClient } from "./websocket-client.js"; + +// 消息处理器 +export { handlePrompt, handleCancel } from "./message-handler.js"; + +// 消息适配器 +export { + extractTextFromContent, + promptPayloadToFuwuhaoMessage, + buildWebSocketMessageContext, +} from "./message-adapter.js"; diff --git a/websocket/message-adapter.ts b/websocket/message-adapter.ts new file mode 100644 index 0000000..9eaa5e1 --- /dev/null +++ b/websocket/message-adapter.ts @@ -0,0 +1,116 @@ +/** + * @file message-adapter.ts + * @description AGP 协议消息与 OpenClaw 内部格式之间的适配器 + * + * 设计思路: + * WebSocket 通道(AGP 协议)和 HTTP 通道(微信服务号 Webhook)使用不同的消息格式, + * 但底层的 Agent 路由、会话管理、消息处理逻辑是完全相同的。 + * 此适配器将 AGP 消息转换为 OpenClaw 内部的 FuwuhaoMessage 格式, + * 从而复用 HTTP 通道已有的 buildMessageContext 逻辑,避免重复实现。 + * + * 转换链路: + * AGP PromptPayload → FuwuhaoMessage → MsgContext(OpenClaw 内部格式) + */ + +import type { PromptPayload, ContentBlock } from "./types.js"; +import type { FuwuhaoMessage } from "../http/types.js"; +import { getWecomRuntime } from "../common/runtime.js"; +import { buildMessageContext } from "../common/message-context.js"; + +// ============================================ +// 消息适配器 +// ============================================ +// 负责 AGP 协议消息与 OpenClaw 内部格式之间的转换 + +/** + * 从 ContentBlock 数组中提取纯文本 + * @param content - AGP 协议的内容块数组(每个块有 type 和 text 字段) + * @returns 合并后的纯文本字符串(多个文本块用换行符连接) + * @description + * AGP 协议的消息内容是结构化的 ContentBlock 数组,支持多种类型(目前只有 text)。 + * 此函数将所有 text 类型的块提取出来,合并为一个纯文本字符串。 + * + * 处理步骤: + * 1. filter: 过滤出 type === "text" 的块(忽略未来可能新增的其他类型) + * 2. map: 提取每个块的 text 字段 + * 3. join: 用换行符连接多个文本块 + * + * 示例: + * ``` + * extractTextFromContent([ + * { type: "text", text: "你好" }, + * { type: "text", text: "请帮我写代码" } + * ]) + * // 返回:"你好\n请帮我写代码" + * ``` + */ +export const extractTextFromContent = (content: ContentBlock[]): string => { + return content + .filter((block) => block.type === "text") + .map((block) => block.text) + .join("\n"); +}; + +/** + * 将 AGP session.prompt 载荷转换为 FuwuhaoMessage 格式 + * @param payload - AGP 协议的 prompt 载荷(包含 session_id、prompt_id、content 等) + * @param userId - 用户 ID(来自 AGP 信封的 user_id 字段) + * @returns OpenClaw 内部的 FuwuhaoMessage 格式 + * @description + * FuwuhaoMessage 是 OpenClaw 为微信服务号定义的内部消息格式, + * 与微信服务号 Webhook 推送的消息格式保持一致。 + * 通过将 AGP 消息转换为此格式,可以复用 HTTP 通道的所有处理逻辑。 + * + * 字段映射: + * - msgtype: 固定为 "text"(当前只支持文本消息) + * - MsgId: 使用 prompt_id 作为消息 ID(保证唯一性) + * - Content: 从 ContentBlock 数组提取的纯文本 + * - FromUserName: 发送者 ID(来自 AGP 信封的 user_id) + * - ToUserName: 固定为 "fuwuhao_bot"(接收方标识) + * - CreateTime: 当前时间戳(秒级,Math.floor(Date.now() / 1000)) + * + * `Date.now()` 返回毫秒级时间戳,除以 1000 并取整得到秒级时间戳, + * 与微信服务号 Webhook 的 CreateTime 字段格式一致。 + */ +export const promptPayloadToFuwuhaoMessage = ( + payload: PromptPayload, + userId: string +): FuwuhaoMessage => { + const textContent = extractTextFromContent(payload.content); + + return { + msgtype: "text", + MsgId: payload.prompt_id, // 使用 prompt_id 作为消息唯一 ID + Content: textContent, + FromUserName: userId, + ToUserName: "fuwuhao_bot", + CreateTime: Math.floor(Date.now() / 1000), // 秒级时间戳 + }; +}; + +/** + * 构建 WebSocket 消息的完整上下文 + * @param payload - AGP 协议的 prompt 载荷 + * @param userId - 用户 ID + * @returns 消息上下文对象,包含: + * - ctx: MsgContext — OpenClaw 内部消息上下文(含路由、会话等信息) + * - route: 路由信息(agentId、accountId、sessionKey 等) + * - storePath: 会话存储文件路径 + * @description + * 这是适配器的核心函数,完成两步转换: + * 1. AGP PromptPayload → FuwuhaoMessage(通过 promptPayloadToFuwuhaoMessage) + * 2. FuwuhaoMessage → MsgContext(通过 buildMessageContext,复用 HTTP 通道逻辑) + * + * buildMessageContext 内部会: + * - 根据消息的 FromUserName 和 ToUserName 确定路由(选择哪个 Agent) + * - 计算 sessionKey(用于关联历史对话) + * - 确定 storePath(会话历史存储位置) + * - 构建完整的 MsgContext(包含所有 Agent 处理所需的上下文信息) + * + * 通过这种适配方式,WebSocket 通道和 HTTP 通道共享同一套路由和会话管理逻辑, + * 确保两个通道的行为完全一致。 + */ +export const buildWebSocketMessageContext = (payload: PromptPayload, userId: string) => { + const message = promptPayloadToFuwuhaoMessage(payload, userId); + return buildMessageContext(message); +}; diff --git a/websocket/message-handler.ts b/websocket/message-handler.ts new file mode 100644 index 0000000..b255a22 --- /dev/null +++ b/websocket/message-handler.ts @@ -0,0 +1,612 @@ +/** + * @file message-handler.ts + * @description WebSocket 消息处理器 + * + * 负责处理从 AGP 服务端收到的下行消息,核心流程: + * 1. 收到 session.prompt → 调用 OpenClaw Agent 处理用户指令 + * 2. 通过 runtime.events.onAgentEvent 监听 Agent 的流式输出 + * 3. 将流式输出实时通过 WebSocket 推送给服务端(session.update) + * 4. Agent 处理完成后发送最终结果(session.promptResponse) + * 5. 收到 session.cancel → 中断正在处理的 Turn + */ + +import type { + PromptMessage, + CancelMessage, + ContentBlock, + ToolCall, +} from "./types.js"; +import { onAgentEvent, type AgentEventPayload } from "../common/agent-events.js"; +import type { WechatAccessWebSocketClient } from "./websocket-client.js"; + +/** 内容安全审核拦截标记,由 content-security 插件的 fetch 拦截器嵌入伪 SSE 响应中 */ +const SECURITY_BLOCK_MARKER = ""; + +/** 安全拦截后返回给微信用户的通用提示文本(不暴露具体拦截原因) */ +const SECURITY_BLOCK_USER_MESSAGE = "抱歉,我无法处理该任务,让我们换个任务试试看?"; + +/** + * `getWecomRuntime` 返回 OpenClaw 框架注入的运行时实例(PluginRuntime)。 + * 运行时提供了访问框架核心功能的统一入口,包括: + * - runtime.config.loadConfig():读取 openclaw 配置文件(~/.openclaw/config.json) + * - runtime.events.onAgentEvent():订阅 Agent 运行时事件(流式输出、工具调用等) + * - runtime.channel.session:会话元数据管理(记录用户会话信息) + * - runtime.channel.activity:渠道活动统计(记录收发消息次数) + * - runtime.channel.reply:消息回复调度(调用 Agent 并分发回复) + */ +import { getWecomRuntime } from "../common/runtime.js"; +import { + extractTextFromContent, + buildWebSocketMessageContext, +} from "./message-adapter.js"; + +// ============================================ +// WebSocket 消息处理器 +// ============================================ +// 接收 AGP 下行消息 → 调用 OpenClaw Agent → 发送 AGP 上行消息 + +/** + * 活跃的 Prompt Turn 追踪器 + * @description + * 每个正在处理中的用户请求(Turn)都会在 activeTurns Map 中注册一条记录。 + * 用于支持取消操作:收到 session.cancel 时,通过 promptId 找到对应的 Turn, + * 将其标记为已取消,并取消 Agent 事件订阅。 + */ +interface ActiveTurn { + sessionId: string; + promptId: string; + /** 是否已被取消(标志位,Agent 事件回调中检查此值决定是否继续处理) */ + cancelled: boolean; + /** + * Agent 事件取消订阅函数。 + * `runtime.events.onAgentEvent()` 返回一个函数,调用该函数可以取消订阅, + * 停止接收后续的 Agent 事件(类似 EventEmitter 的 removeListener)。 + */ + unsubscribe?: () => void; +} + +/** + * 当前活跃的 Turn 映射(promptId → ActiveTurn) + * @description + * 使用 Map 而非对象,因为 Map 的 key 可以是任意类型,且有更好的增删性能。 + * promptId 是服务端分配的唯一 Turn ID,用于关联 prompt 和 cancel 消息。 + */ +const activeTurns = new Map(); + +/** + * 处理 session.prompt 消息 — 接收用户指令并调用 Agent + * @param message - AGP session.prompt 消息(包含用户指令内容) + * @param client - WebSocket 客户端实例(用于发送上行消息回服务端) + * @description + * 完整处理流程: + * + * ``` + * 服务端 → session.prompt + * ↓ + * 1. 注册 ActiveTurn(支持后续取消) + * ↓ + * 2. getWecomRuntime() 获取运行时 + * ↓ + * 3. runtime.config.loadConfig() 读取配置 + * ↓ + * 4. buildWebSocketMessageContext() 构建消息上下文(路由、会话路径等) + * ↓ + * 5. runtime.channel.session.recordSessionMetaFromInbound() 记录会话元数据 + * ↓ + * 6. runtime.channel.activity.record() 记录入站活动统计 + * ↓ + * 7. runtime.events.onAgentEvent() 订阅 Agent 流式事件 + * ↓ + * 8. runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher() 调用 Agent + * ↓ (Agent 运行期间,步骤 7 的回调持续触发) + * ├── assistant 流 → client.sendMessageChunk() → session.update(message_chunk) + * └── tool 流 → client.sendToolCall/sendToolCallUpdate() → session.update(tool_call) + * ↓ + * 9. client.sendPromptResponse() → session.promptResponse(最终结果) + * ``` + */ +export const handlePrompt = async ( + message: PromptMessage, + client: WechatAccessWebSocketClient +): Promise => { + const { payload } = message; + const { session_id: sessionId, prompt_id: promptId } = payload; + const userId = message.user_id ?? ""; + const guid = message.guid ?? ""; + //message { + // msg_id: '9b842a47-c07d-4307-974f-42a4f8eeecb4', + // guid: '0ef9cc5e5dcb7ca068b0fb9982352c33', + // user_id: '3730000', + // method: 'session.prompt', + // payload: { + // session_id: '384f885b-4387-4f2b-9233-89a5fe6f94ee', + // prompt_id: 'ca694ac8-35e3-4e8b-9ecc-88efd4324515', + // agent_app: 'agent_demo', + // content: [ [Object] ] + // } + // } + const textContent = extractTextFromContent(payload.content); + console.log("[wechat-access-ws] 收到 prompt:", payload); + + // ============================================ + // 1. 注册活跃 Turn + // ============================================ + // 在 activeTurns Map 中注册此次请求,以便 handleCancel 能找到并取消它 + const turn: ActiveTurn = { + sessionId, + promptId, + cancelled: false, + }; + activeTurns.set(promptId, turn); + + try { + /** + * getWecomRuntime() 返回 OpenClaw 框架的运行时实例(PluginRuntime)。 + * 这是一个单例,在插件初始化时由 setWecomRuntime(api.runtime) 注入。 + * 如果未初始化就调用会抛出错误。 + */ + const runtime = getWecomRuntime(); + + /** + * runtime.config.loadConfig() 同步读取 OpenClaw 配置文件。 + * 配置文件通常位于 ~/.openclaw/config.json,包含: + * - Agent 配置(模型、系统提示词等) + * - 渠道配置(各渠道的账号信息) + * - 会话存储路径等 + * 返回的 cfg 对象在后续的 dispatchReplyWithBufferedBlockDispatcher 中使用。 + */ + const cfg = runtime.config.loadConfig(); + + // ============================================ + // 2. 构建消息上下文 + // ============================================ + /** + * buildWebSocketMessageContext() 将 AGP 消息转换为 OpenClaw 内部的消息上下文格式。 + * 返回值包含: + * - ctx: MsgContext — 消息上下文(包含 From、To、SessionKey、AgentId 等字段) + * - route: 路由信息(agentId、accountId、sessionKey 等) + * - storePath: 会话存储文件路径(如 ~/.openclaw/sessions/agent-xxx.json) + * + * 这样可以复用 HTTP 通道的路由和会话管理逻辑,保持一致性。 + */ + const { ctx, route, storePath } = buildWebSocketMessageContext(payload, userId); + + console.log("[wechat-access-ws] 路由信息:", { + sessionKey: route.sessionKey, + agentId: route.agentId, + accountId: route.accountId, + }); + + // ============================================ + // 3. 记录会话元数据 + // ============================================ + /** + * runtime.channel.session.recordSessionMetaFromInbound() 将本次消息的元数据 + * 写入会话存储文件(storePath 指向的 JSON 文件)。 + * 元数据包括:用户 ID、渠道类型、最后活跃时间等。 + * 这些数据用于会话管理、上下文恢复等功能。 + * + * 使用 void + .catch() 的原因: + * - void: 明确表示不等待此 Promise(不阻塞主流程) + * - .catch(): 捕获错误并打印日志,避免未处理的 Promise rejection + * 会话元数据写入失败不影响消息处理,所以不需要 await。 + */ + void runtime.channel.session + .recordSessionMetaFromInbound({ + storePath, + sessionKey: (ctx.SessionKey as string) ?? route.sessionKey, + ctx, + }) + .catch((err: unknown) => { + console.log(`[wechat-access-ws] 记录会话元数据失败: ${String(err)}`); + }); + + // ============================================ + // 4. 记录入站活动 + // ============================================ + /** + * runtime.channel.activity.record() 记录渠道活动统计数据。 + * direction: "inbound" 表示这是一条收到的消息(用户 → 系统)。 + * 这些统计数据用于 OpenClaw 控制台的活动监控面板。 + */ + runtime.channel.activity.record({ + channel: "wechat-access", + accountId: route.accountId ?? "default", + direction: "inbound", + }); + + // ============================================ + // 5. 订阅 Agent 事件(流式输出) + // ============================================ + /** + * runtime.events.onAgentEvent() 注册一个全局 Agent 事件监听器。 + * 当 Agent 运行时,会通过事件总线(EventEmitter)广播各种事件。 + * + * AgentEventPayload 结构: + * { + * runId: string; // Agent 运行实例 ID + * seq: number; // 事件序号(严格递增,用于检测丢失事件) + * stream: string; // 事件流类型(见下方说明) + * ts: number; // 时间戳(毫秒) + * data: Record; // 事件数据(不同 stream 有不同结构) + * sessionKey?: string; // 关联的会话 key + * } + * + * stream 类型说明: + * - "assistant": AI 助手的文本输出流 + * data.delta: 增量文本(本次新增的部分) + * data.text: 累积文本(从开始到现在的完整文本) + * - "tool": 工具调用流 + * data.phase: 阶段("start" | "update" | "result") + * data.name: 工具名称(如 "read_file"、"write") + * data.toolCallId: 工具调用唯一 ID + * data.args: 工具参数(phase=start 时) + * data.result: 工具执行结果(phase=result 时) + * data.isError: 是否执行失败(phase=result 时) + * - "lifecycle": 生命周期事件(start/end/error) + * - "compaction": 上下文压缩事件 + * + * 返回值是取消订阅函数,调用后停止接收事件。 + * 注意:这是全局事件总线,所有 Agent 运行的事件都会触发此回调, + * 但目前没有按 runId 过滤(因为同一时间通常只有一个 Agent 在运行)。 + */ + let lastEmittedText = ""; // 记录已发送的累积文本,用于计算增量 + let toolCallCounter = 0; // 工具调用计数器,用于生成备用 toolCallId + + // await 确保 SDK 加载完成、监听器真正挂载后,再调用 dispatchReply + // 否则 Agent 产生事件时监听器还未注册,导致所有事件丢失 + const unsubscribe = await onAgentEvent((evt: AgentEventPayload) => { + // 如果 Turn 已被取消,忽略后续事件(不再向服务端推送) + if (turn.cancelled) return; + // 过滤非本 Turn 的事件,避免并发多个 prompt 时事件串流 + if (evt.sessionKey && evt.sessionKey !== route.sessionKey) return; + + const data = evt.data as Record; + + // --- 处理流式文本(assistant 流)--- + if (evt.stream === "assistant") { + /** + * Agent 生成文本时,事件总线会持续触发 assistant 流事件。 + * 每个事件包含: + * - data.delta: 本次新增的文本片段(增量) + * - data.text: 从开始到现在的完整文本(累积) + * + * 优先使用 delta(增量),因为它直接就是需要发送的内容。 + * 如果没有 delta(某些 AI 提供商只提供累积文本), + * 则通过 text.slice(lastEmittedText.length) 手动计算增量。 + */ + const delta = data.delta as string | undefined; + const text = data.text as string | undefined; + + let textToSend = delta; + if (!textToSend && text && text !== lastEmittedText) { + // 手动计算增量:新的累积文本 - 已发送的累积文本 = 本次增量 + textToSend = text.slice(lastEmittedText.length); + lastEmittedText = text; + } else if (delta) { + lastEmittedText += delta; + } + + // 检测安全审核拦截标记:如果流式文本中包含拦截标记,停止向用户推送 + // 拦截标记由 content-security 插件的 fetch 拦截器注入伪 SSE 响应 + if (textToSend && textToSend.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access-ws] 流式文本中检测到安全审核拦截标记,停止推送"); + turn.cancelled = true; // 标记为已取消,阻止后续流式事件继续推送 + return; + } + if (lastEmittedText.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access-ws] 累积文本中检测到安全审核拦截标记,停止推送"); + turn.cancelled = true; + return; + } + + if (textToSend) { + // 将增量文本作为 session.update(message_chunk) 发送给服务端 + client.sendMessageChunk(sessionId, promptId, { + type: "text", + text: textToSend, + }, guid, userId); + } + return; + } + + // --- 处理工具调用事件(tool 流)--- + if (evt.stream === "tool") { + /** + * 工具调用有三个阶段(phase): + * - "start": 工具开始执行(发送 tool_call,status=in_progress) + * - "update": 工具执行中有中间结果(发送 tool_call_update,status=in_progress) + * - "result": 工具执行完成(发送 tool_call_update,status=completed/failed) + * + * toolCallId 是工具调用的唯一标识,用于关联同一次工具调用的多个事件。 + * 如果 Agent 没有提供 toolCallId,则用计数器生成一个备用 ID。 + */ + const phase = data.phase as string | undefined; + const toolName = data.name as string | undefined; + const toolCallId = (data.toolCallId as string) || `tc-${++toolCallCounter}`; + + if (phase === "start") { + // 工具开始执行:通知服务端展示工具调用状态(进行中) + const toolCall: ToolCall = { + tool_call_id: toolCallId, + title: toolName, + kind: mapToolKind(toolName), // 根据工具名推断工具类型(read/edit/search 等) + status: "in_progress", + }; + client.sendToolCall(sessionId, promptId, toolCall, guid, userId); + } else if (phase === "update") { + // 工具执行中有中间结果(如读取文件的部分内容) + const toolCall: ToolCall = { + tool_call_id: toolCallId, + title: toolName, + status: "in_progress", + content: data.text + ? [{ type: "text" as const, text: data.text as string }] + : undefined, + }; + client.sendToolCallUpdate(sessionId, promptId, toolCall, guid, userId); + } else if (phase === "result") { + // 工具执行完成:更新状态为 completed 或 failed + const isError = data.isError as boolean | undefined; + const toolCall: ToolCall = { + tool_call_id: toolCallId, + title: toolName, + status: isError ? "failed" : "completed", + // 将工具执行结果作为内容块附加(可选,用于展示) + content: data.result + ? [{ type: "text" as const, text: data.result as string }] + : undefined, + }; + client.sendToolCallUpdate(sessionId, promptId, toolCall, guid, userId); + } + return; + } + }); + + // 将取消订阅函数保存到 Turn 记录中,以便 handleCancel 调用 + turn.unsubscribe = unsubscribe; + + // ============================================ + // 6. 调用 Agent 处理消息 + // ============================================ + /** + * runtime.channel.reply.resolveEffectiveMessagesConfig() 解析当前 Agent 的消息配置。 + * 返回值包含: + * - responsePrefix: 回复前缀(如果配置了的话) + * - 其他消息格式配置 + * 参数 route.agentId 指定要查询哪个 Agent 的配置。 + */ + const messagesConfig = runtime.channel.reply.resolveEffectiveMessagesConfig( + cfg, + route.agentId + ); + + let finalText: string | null = null; + + /** + * runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher() 是核心调用。 + * 它完成以下工作: + * 1. 根据 ctx(消息上下文)和 cfg(配置)确定使用哪个 Agent + * 2. 加载该 Agent 的历史会话记录(上下文) + * 3. 调用 AI 模型生成回复(流式) + * 4. 在生成过程中,通过事件总线广播 assistant/tool 流事件(步骤 5 的回调会收到) + * 5. 将生成的回复通过 dispatcherOptions.deliver 回调交付 + * 6. 保存本次对话到会话历史 + * + * "BufferedBlockDispatcher" 的含义: + * - Buffered: 将流式输出缓冲后再交付(避免过于频繁的回调) + * - Block: 按块(段落/句子)分割回复 + * - Dispatcher: 负责将回复分发给 deliver 回调 + * + * 返回值 { queuedFinal } 包含最终排队的回复内容(此处未使用,通过 deliver 回调获取)。 + * + * 注意:此函数是 async 的,会等待 Agent 完全处理完毕才 resolve。 + * 在等待期间,步骤 5 注册的 onAgentEvent 回调会持续被触发(流式推送)。 + */ + const { queuedFinal } = await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({ + ctx, + cfg, + dispatcherOptions: { + responsePrefix: messagesConfig.responsePrefix, + /** + * deliver 回调:当 Agent 生成了一个完整的回复块时调用。 + * @param payload - 回复内容(text、mediaUrl 等) + * @param info - 回复元信息(kind: "final" | "chunk" | "error" 等) + * + * 这里主要用于: + * 1. 捕获最终回复文本(finalText) + * 2. 记录出站活动统计 + * + * 注意:流式文本已经通过 onAgentEvent 的 assistant 流实时推送了, + * 这里的 deliver 是最终汇总的回调,用于获取完整的最终文本。 + */ + deliver: async ( + payload: { + text?: string; + mediaUrl?: string; + mediaUrls?: string[]; + isError?: boolean; + channelData?: unknown; + }, + info: { kind: string } + ) => { + if (turn.cancelled) return; + + console.log(`[wechat-access-ws] Agent ${info.kind} 回复:`, payload.text?.slice(0, 50)); + + // 保存最终回复文本,用于构建 session.promptResponse 的 content + // 不限制 kind,只要有 text 就更新(final/chunk 都可能携带完整文本) + if (payload.text) { + // 检测安全审核拦截标记:如果回复文本包含拦截标记, + // 替换为通用安全提示,不向用户暴露具体拦截原因和内部标记 + if (payload.text.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access-ws] deliver 回复中检测到安全审核拦截标记,替换为安全提示"); + finalText = SECURITY_BLOCK_USER_MESSAGE; + } else { + finalText = payload.text; + } + } + + // 记录出站活动统计(每次 deliver 都算一次出站) + runtime.channel.activity.record({ + channel: "wechat-access", + accountId: route.accountId ?? "default", + direction: "outbound", + }); + }, + onError: (err: unknown, info: { kind: string }) => { + console.error(`[wechat-access-ws] Agent ${info.kind} 回复失败:`, err); + }, + }, + replyOptions: {}, + }); + + // ============================================ + // 7. 发送最终结果 + // ============================================ + // Agent 处理完成,取消事件订阅并清理 Turn 记录 + unsubscribe(); + activeTurns.delete(promptId); + + if (turn.cancelled) { + // 如果在 Agent 处理期间收到了 cancel 消息,发送 cancelled 响应 + client.sendPromptResponse({ + session_id: sessionId, + prompt_id: promptId, + stop_reason: "cancelled", + }, guid, userId); + return; + } + + // 构建最终内容块(如果有文本回复的话) + // 优先用 deliver 回调收到的 finalText,兜底用流式事件累积的 lastEmittedText + let replyText = finalText || (lastEmittedText.trim() ? lastEmittedText : null); + + // 最后一道防线:检查最终回复文本是否包含安全拦截标记 + // 正常情况下 deliver 回调和流式事件中已经处理过了,这里是兜底 + if (replyText && replyText.includes(SECURITY_BLOCK_MARKER)) { + console.warn("[wechat-access-ws] 最终回复文本中检测到安全审核拦截标记,替换为安全提示"); + replyText = SECURITY_BLOCK_USER_MESSAGE; + } + + const responseContent: ContentBlock[] = replyText + ? [{ type: "text", text: replyText }] + : []; + + // 发送 session.promptResponse,告知服务端本次 Turn 已正常完成 + client.sendPromptResponse({ + session_id: sessionId, + prompt_id: promptId, + stop_reason: "end_turn", + content: responseContent, + }, guid, userId); + + console.log("[wechat-access-ws] prompt 处理完成:", { promptId, hasReply: !!replyText, finalText: !!finalText, lastEmittedText: lastEmittedText.length }); + } catch (err) { + // ============================================ + // 错误处理 + // ============================================ + console.error("[wechat-access-ws] prompt 处理失败:", err); + + // 清理活跃 Turn(取消事件订阅,从 Map 中移除) + const currentTurn = activeTurns.get(promptId); + currentTurn?.unsubscribe?.(); + activeTurns.delete(promptId); + + // 发送错误响应,告知服务端本次 Turn 因错误终止 + client.sendPromptResponse({ + session_id: sessionId, + prompt_id: promptId, + stop_reason: "error", + error: err instanceof Error ? err.message : String(err), + }, guid, userId); + } +}; + +/** + * 处理 session.cancel 消息 — 取消正在处理的 Prompt Turn + * @param message - AGP session.cancel 消息 + * @param client - WebSocket 客户端实例 + * @description + * 取消流程: + * 1. 通过 promptId 在 activeTurns Map 中查找对应的 Turn + * 2. 将 turn.cancelled 标记为 true(handlePrompt 中的 onAgentEvent 回调会检查此标志) + * 3. 调用 turn.unsubscribe() 停止接收后续 Agent 事件 + * 4. 从 activeTurns 中移除此 Turn + * 5. 发送 session.promptResponse(stop_reason: "cancelled") + * + * 注意:取消操作是"尽力而为"的,Agent 可能已经处理完毕, + * 此时 activeTurns 中找不到对应 Turn,但仍然发送 cancelled 响应。 + */ +export const handleCancel = ( + message: CancelMessage, + client: WechatAccessWebSocketClient +): void => { + const { session_id: sessionId, prompt_id: promptId } = message.payload; + + console.log("[wechat-access-ws] 收到 cancel:", { sessionId, promptId }); + + const turn = activeTurns.get(promptId); + if (!turn) { + console.warn(`[wechat-access-ws] 未找到活跃 Turn: ${promptId}`); + // 即使找不到对应 Turn(可能已处理完毕),也发送 cancelled 响应 + // 确保服务端收到明确的结束信号 + client.sendPromptResponse({ + session_id: sessionId, + prompt_id: promptId, + stop_reason: "cancelled", + }); + return; + } + + // 标记为已取消:handlePrompt 中的 onAgentEvent 回调会检查此标志, + // 一旦为 true,后续的流式事件都会被忽略,不再向服务端推送 + turn.cancelled = true; + + // 取消 Agent 事件订阅,停止接收后续事件 + // 可选链 ?.() 是因为 unsubscribe 可能还未赋值(Turn 刚注册但还未到步骤 5) + turn.unsubscribe?.(); + activeTurns.delete(promptId); + + // 发送 cancelled 响应 + client.sendPromptResponse({ + session_id: sessionId, + prompt_id: promptId, + stop_reason: "cancelled", + }); + + console.log("[wechat-access-ws] Turn 已取消:", promptId); +}; + +// ============================================ +// 辅助函数 +// ============================================ + +/** + * 将工具名称映射为 AGP 协议的 ToolCallKind + * @param toolName - 工具名称(如 "read_file"、"write"、"grep_search" 等) + * @returns ToolCallKind 枚举值,用于服务端展示不同类型的工具调用图标 + * @description + * 通过关键词匹配推断工具类型,映射规则: + * - read/get/view → "read"(读取操作) + * - write/edit/replace → "edit"(编辑操作) + * - delete/remove → "delete"(删除操作) + * - search/find/grep → "search"(搜索操作) + * - fetch/request/http → "fetch"(网络请求) + * - think/reason → "think"(思考/推理) + * - exec/run/terminal → "execute"(执行命令) + * - 其他 → "other" + */ +const mapToolKind = (toolName?: string): ToolCall["kind"] => { + if (!toolName) return "other"; + + const name = toolName.toLowerCase(); + if (name.includes("read") || name.includes("get") || name.includes("view")) return "read"; + if (name.includes("write") || name.includes("edit") || name.includes("replace")) return "edit"; + if (name.includes("delete") || name.includes("remove")) return "delete"; + if (name.includes("search") || name.includes("find") || name.includes("grep")) return "search"; + if (name.includes("fetch") || name.includes("request") || name.includes("http")) return "fetch"; + if (name.includes("think") || name.includes("reason")) return "think"; + if (name.includes("exec") || name.includes("run") || name.includes("terminal")) return "execute"; + return "other"; +}; diff --git a/websocket/types.ts b/websocket/types.ts new file mode 100644 index 0000000..9ef9f22 --- /dev/null +++ b/websocket/types.ts @@ -0,0 +1,290 @@ +/** + * @file types.ts + * @description AGP (Agent Gateway Protocol) 协议类型定义 + * + * AGP 是 OpenClaw 与外部服务(如微信服务号后端)之间的 WebSocket 通信协议。 + * 所有消息都使用统一的「信封(Envelope)」格式,通过 method 字段区分消息类型。 + * + * 消息方向: + * 下行(服务端 → 客户端):session.prompt、session.cancel + * 上行(客户端 → 服务端):session.update、session.promptResponse + * + * 基于 websocket.md 协议文档定义 + */ + +// ============================================ +// AGP 消息信封 +// ============================================ +/** + * AGP 统一消息信封 + * 所有 WebSocket 消息(上行和下行)均使用此格式 + */ +export interface AGPEnvelope { + /** 全局唯一消息 ID(UUID),用于幂等去重 */ + msg_id: string; + /** 设备唯一标识(下行消息携带,上行消息需原样回传) */ + guid?: string; + /** 用户 ID(下行消息携带,上行消息需原样回传) */ + user_id?: string; + /** 消息类型 */ + method: AGPMethod; + /** 消息载荷 */ + payload: T; +} + +// ============================================ +// Method 枚举 +// ============================================ +/** + * AGP 消息方法枚举 + * - session.prompt: 下发用户指令(服务端 → 客户端) + * - session.cancel: 取消 Prompt Turn(服务端 → 客户端) + * - session.update: 流式中间更新(客户端 → 服务端) + * - session.promptResponse: 最终结果(客户端 → 服务端) + */ +export type AGPMethod = + | "session.prompt" + | "session.cancel" + | "session.update" + | "session.promptResponse" + | "ping"; + +// ============================================ +// 通用数据结构 +// ============================================ + +/** + * 内容块 + * 当前仅支持 text 类型 + */ +export interface ContentBlock { + type: "text"; + text: string; +} + +/** + * 工具调用状态枚举 + */ +export type ToolCallStatus = "pending" | "in_progress" | "completed" | "failed"; + +/** + * 工具调用类型枚举 + */ +export type ToolCallKind = "read" | "edit" | "delete" | "execute" | "search" | "fetch" | "think" | "other"; + +/** + * 工具操作路径 + * @description 记录工具调用涉及的文件或目录路径,用于在 UI 中展示操作位置 + */ +export interface ToolLocation { + /** 文件或目录的绝对路径 */ + path: string; +} + +/** + * 工具调用 + * @description + * 描述一次工具调用的完整信息,用于在 session.update 消息中实时推送工具执行状态。 + * 一次工具调用会产生多个 session.update 消息: + * 1. update_type=tool_call:工具开始执行(status=in_progress) + * 2. update_type=tool_call_update:执行中间状态(status=in_progress,可选) + * 3. update_type=tool_call_update:执行完成(status=completed/failed) + */ +export interface ToolCall { + /** 工具调用唯一 ID,用于关联同一次工具调用的多个 update 消息 */ + tool_call_id: string; + /** 工具调用标题(展示用,通常是工具名称,如 "read_file") */ + title?: string; + /** 工具类型,用于 UI 展示不同的图标 */ + kind?: ToolCallKind; + /** 工具调用当前状态 */ + status: ToolCallStatus; + /** 工具调用结果内容(phase=result 时附带,用于展示工具输出) */ + content?: ContentBlock[]; + /** 工具操作涉及的文件路径(可选,用于 UI 展示操作位置) */ + locations?: ToolLocation[]; +} + +// ============================================ +// 下行消息(服务端 → 客户端) +// ============================================ + +/** + * session.prompt 载荷 — 下发用户指令 + * @description + * 服务端收到用户消息后,通过此消息将用户指令下发给客户端(OpenClaw Agent)处理。 + * 客户端处理完毕后,需要发送 session.promptResponse 作为响应。 + */ +export interface PromptPayload { + /** 所属 Session ID(标识一个完整的对话会话) */ + session_id: string; + /** 本次 Turn 唯一 ID(标识一次「用户提问 + AI 回答」的完整交互) */ + prompt_id: string; + /** 目标 AI 应用标识(指定由哪个 Agent 处理此消息) */ + agent_app: string; + /** 用户指令内容(结构化内容块数组,目前只支持 text 类型) */ + content: ContentBlock[]; +} + +/** + * session.cancel 载荷 — 取消 Prompt Turn + * @description + * 用户主动取消正在处理的请求时,服务端发送此消息。 + * 客户端收到后应停止 Agent 处理,并发送 stop_reason=cancelled 的 promptResponse。 + */ +export interface CancelPayload { + /** 所属 Session ID */ + session_id: string; + /** 要取消的 Turn ID(与对应 session.prompt 的 prompt_id 一致) */ + prompt_id: string; + /** 目标 AI 应用标识 */ + agent_app: string; +} + +// ============================================ +// 上行消息(客户端 → 服务端) +// ============================================ + +/** + * session.update 的更新类型 + * @description + * 定义 session.update 消息中 update_type 字段的可选值: + * - message_chunk: Agent 生成的增量文本片段(流式输出,每次只包含新增的部分) + * - tool_call: Agent 开始调用一个工具(通知服务端展示工具调用状态) + * - tool_call_update: 工具调用状态变更(执行中的中间结果,或执行完成/失败) + */ +export type UpdateType = "message_chunk" | "tool_call" | "tool_call_update"; + +/** + * session.update 载荷 — 流式中间更新 + * @description + * 在 Agent 处理 session.prompt 的过程中,通过此消息实时推送中间状态。 + * 服务端收到后转发给用户端,实现流式输出效果。 + * + * 根据 update_type 的不同,使用不同的字段: + * - message_chunk: 使用 content 字段(单个 ContentBlock,非数组) + * - tool_call / tool_call_update: 使用 tool_call 字段 + */ +export interface UpdatePayload { + /** 所属 Session ID */ + session_id: string; + /** 所属 Turn ID(与对应 session.prompt 的 prompt_id 一致) */ + prompt_id: string; + /** 更新类型,决定使用 content 还是 tool_call 字段 */ + update_type: UpdateType; + /** + * 文本内容块(update_type=message_chunk 时使用) + * 注意:这里是单个 ContentBlock 对象,而非数组 + */ + content?: ContentBlock; + /** 工具调用信息(update_type=tool_call 或 tool_call_update 时使用) */ + tool_call?: ToolCall; +} + +/** + * 停止原因枚举 + * - end_turn: 正常完成 + * - cancelled: 被取消 + * - refusal: AI 应用拒绝执行 + * - error: 技术错误 + */ +export type StopReason = "end_turn" | "cancelled" | "refusal" | "error"; + +/** + * session.promptResponse 载荷 — 最终结果 + * @description + * Agent 处理完 session.prompt 后,必须发送此消息告知服务端本次 Turn 已结束。 + * 无论正常完成、被取消还是出错,都需要发送此消息。 + * 服务端收到后才会认为本次 Turn 已关闭,可以接受下一个 prompt。 + */ +export interface PromptResponsePayload { + /** 所属 Session ID */ + session_id: string; + /** 所属 Turn ID(与对应 session.prompt 的 prompt_id 一致) */ + prompt_id: string; + /** 停止原因,告知服务端 Turn 是如何结束的 */ + stop_reason: StopReason; + /** + * 最终结果内容(ContentBlock 数组) + * stop_reason=end_turn 时附带,包含 Agent 的完整回复文本 + * stop_reason=cancelled/error 时通常为空 + */ + content?: ContentBlock[]; + /** 错误描述(stop_reason 为 error 或 refusal 时附带,说明失败原因) */ + error?: string; +} + +// ============================================ +// 类型别名(方便使用) +// ============================================ + +/** 下行:session.prompt 消息 */ +export type PromptMessage = AGPEnvelope; +/** 下行:session.cancel 消息 */ +export type CancelMessage = AGPEnvelope; +/** 上行:session.update 消息 */ +export type UpdateMessage = AGPEnvelope; +/** 上行:session.promptResponse 消息 */ +export type PromptResponseMessage = AGPEnvelope; + +// ============================================ +// WebSocket 客户端配置 +// ============================================ + +/** + * WebSocket 客户端配置 + * @description + * 在插件入口(index.ts)的 WS_CONFIG 常量中配置,传入 WechatAccessWebSocketClient 构造函数。 + */ +export interface WebSocketClientConfig { + /** WebSocket 服务端地址(如 ws://21.0.62.97:8080/) */ + url: string; + /** 设备唯一标识,用于服务端识别连接来源(作为 URL 查询参数传递) */ + guid: string; + /** 用户账户 ID(作为 URL 查询参数传递,也用于上行消息的 user_id 字段) */ + userId: string; + /** 鉴权 token(可选,作为 URL 查询参数传递,当前服务端未校验) */ + token?: string; + /** + * 重连间隔基准值(毫秒),默认 3000(3秒) + * 实际重连间隔使用指数退避策略,此值是第一次重连的等待时间 + */ + reconnectInterval?: number; + /** + * 最大重连次数,默认 0(无限重连) + * 设为正整数时,超过此次数后停止重连并将状态设为 disconnected + */ + maxReconnectAttempts?: number; + /** + * 心跳间隔(毫秒),默认 240000(4分钟) + * 应小于服务端的空闲超时时间(通常为 5 分钟),确保连接不会因空闲被断开 + * 心跳使用 WebSocket 原生 ping 控制帧(ws 库的 ws.ping() 方法) + */ + heartbeatInterval?: number; + /** + * 当前 openclaw gateway 监听的端口号(来自 cfg.gateway.port) + * 用于日志前缀,方便区分多实例 + */ + gatewayPort?: string; +} + +/** + * WebSocket 连接状态 + */ +export type ConnectionState = "disconnected" | "connecting" | "connected" | "reconnecting"; + +/** + * WebSocket 客户端事件回调 + */ +export interface WebSocketClientCallbacks { + /** 连接成功 */ + onConnected?: () => void; + /** 连接断开 */ + onDisconnected?: (reason?: string) => void; + /** 收到 session.prompt 消息 */ + onPrompt?: (message: PromptMessage) => void; + /** 收到 session.cancel 消息 */ + onCancel?: (message: CancelMessage) => void; + /** 发生错误 */ + onError?: (error: Error) => void; +} diff --git a/websocket/websocket-client.ts b/websocket/websocket-client.ts new file mode 100644 index 0000000..065ab2d --- /dev/null +++ b/websocket/websocket-client.ts @@ -0,0 +1,739 @@ +/** + * `randomUUID` 来自 Node.js 内置的 `node:crypto` 模块。 + * 用于生成符合 RFC 4122 标准的 UUID v4 字符串,格式如: + * "550e8400-e29b-41d4-a716-446655440000" + * 每次调用都会生成一个全局唯一的随机字符串,用作消息的 msg_id。 + * 注意:这是 Node.js 原生 API,不需要安装任何第三方库。 + */ +import { randomUUID } from "node:crypto"; +import WebSocket from "ws"; +import type { + AGPEnvelope, + AGPMethod, + WebSocketClientConfig, + ConnectionState, + WebSocketClientCallbacks, + PromptMessage, + CancelMessage, + UpdatePayload, + PromptResponsePayload, + ContentBlock, + ToolCall, +} from "./types.js"; + +// ============================================ +// WebSocket 客户端核心 +// ============================================ +// 负责 WebSocket 连接管理、消息收发、自动重连、心跳保活 + +/** + * WebSocket 客户端 + * @description + * 连接到 AGP WebSocket 服务端,处理双向通信: + * - 接收下行消息:session.prompt / session.cancel + * - 发送上行消息:session.update / session.promptResponse + * - 自动重连:连接断开后自动尝试重连(指数退避策略) + * - 心跳保活:定期发送 WebSocket 原生 ping 帧,防止服务端因空闲超时断开连接 + * - 消息去重:通过 msg_id 实现幂等处理,避免重复消息被处理两次 + */ +export class WechatAccessWebSocketClient { + private config: Required> & { token?: string; gatewayPort?: string }; + private callbacks: WebSocketClientCallbacks; + + /** + * ws 库的 WebSocket 实例。 + * 类型写作 `WebSocket.WebSocket` 是因为 ws 库的默认导出是类本身, + * 而 `WebSocket.WebSocket` 是其实例类型(TypeScript 类型系统的要求)。 + * 未连接时为 null。 + */ + private ws: WebSocket | null = null; + + /** 当前连接状态 */ + private state: ConnectionState = "disconnected"; + + /** + * 重连定时器句柄。 + * `ReturnType` 是 TypeScript 推荐的写法, + * 可以同时兼容 Node.js(返回 Timeout 对象)和浏览器(返回 number)环境。 + */ + private reconnectTimer: ReturnType | null = null; + + /** + * 心跳定时器句柄。 + * `ReturnType` 同上,兼容 Node.js 和浏览器。 + */ + private heartbeatTimer: ReturnType | null = null; + + /** 当前已尝试的重连次数 */ + private reconnectAttempts = 0; + + /** + * 已处理的消息 ID 集合(用于去重)。 + * 使用 Set 而非数组,查找时间复杂度为 O(1)。 + * 当消息因网络问题被重发时,通过检查 msg_id 是否已存在来避免重复处理。 + */ + private processedMsgIds = new Set(); + + /** 消息 ID 缓存定期清理定时器(防止 Set 无限增长导致内存泄漏) */ + private msgIdCleanupTimer: ReturnType | null = null; + + /** 上次收到 pong 的时间戳(用于检测连接假死) */ + private lastPongTime = Date.now(); + + /** 系统唤醒检测定时器 */ + private wakeupCheckTimer: ReturnType | null = null; + + /** 唤醒检测:上次 tick 的时间戳 */ + private lastTickTime = Date.now(); + + /** 消息 ID 缓存的最大容量,超过此值时触发清理 */ + private static readonly MAX_MSG_ID_CACHE = 1000; + + /** 从 config.url 中解析出端口号,用于日志前缀 */ + private get port(): string { + return this.config.gatewayPort ?? 'unknown'; + } + + /** 带端口号的日志前缀 */ + private get logPrefix(): string { + return `[wechat-access-ws:${this.port}]`; + } + + constructor(config: WebSocketClientConfig, callbacks: WebSocketClientCallbacks = {}) { + this.config = { + url: config.url, + guid: config.guid ?? '', + userId: config.userId ?? '', + token: config.token, + gatewayPort: config.gatewayPort, + reconnectInterval: config.reconnectInterval ?? 3000, + maxReconnectAttempts: config.maxReconnectAttempts ?? 0, + // 默认 20s发一次心跳,小于服务端 1 分钟的空闲超时时间 + heartbeatInterval: config.heartbeatInterval ?? 20000, + }; + this.callbacks = callbacks; + } + + /** + * 启动 WebSocket 连接 + * @description + * 如果当前已连接或正在连接中,则直接返回,避免重复建立连接。 + * 同时启动消息 ID 缓存的定期清理任务。 + */ + start = (): void => { + if (this.state === "connected" || this.state === "connecting") { + console.log(`${this.logPrefix} 已连接或正在连接,跳过`); + return; + } + this.connect(); + this.startMsgIdCleanup(); + }; + + /** + * 停止 WebSocket 连接 + * @description + * 主动断开连接时调用。会: + * 1. 将状态设为 "disconnected"(阻止断开后触发自动重连) + * 2. 清理所有定时器(重连、心跳、消息 ID 清理) + * 3. 清空消息 ID 缓存 + * 4. 关闭 WebSocket 连接 + */ + stop = (): void => { + console.log(`${this.logPrefix} 正在停止...`); + this.state = "disconnected"; + this.clearReconnectTimer(); + this.clearHeartbeat(); + this.clearWakeupDetection(); + this.clearMsgIdCleanup(); + this.processedMsgIds.clear(); + + if (this.ws) { + this.ws.close(); + this.ws = null; + } + console.log(`${this.logPrefix} 已停止`); + }; + + /** + * 获取当前连接状态 + * @returns "disconnected" | "connecting" | "connected" | "reconnecting" + */ + getState = (): ConnectionState => this.state; + + /** + * 更新事件回调 + * @description 使用对象展开合并,只更新传入的回调,保留未传入的原有回调 + */ + setCallbacks = (callbacks: Partial): void => { + this.callbacks = { ...this.callbacks, ...callbacks }; + }; + + /** + * 发送 session.update 消息 — 流式中间更新(文本块) + * @param sessionId - 所属 Session ID + * @param promptId - 所属 Turn ID + * @param content - 文本内容块(type: "text") + * @description + * 在 Agent 生成回复的过程中,将增量文本实时推送给服务端, + * 服务端再转发给用户端展示流式输出效果。 + */ + sendMessageChunk = (sessionId: string, promptId: string, content: ContentBlock, guid?: string, userId?: string): void => { + console.log(`${this.logPrefix} [sendMessageChunk] sessionId=${sessionId}, promptId=${promptId}, guid=${guid}, userId=${userId}, content=${JSON.stringify(content).substring(0, 200)}`); + const payload: UpdatePayload = { + session_id: sessionId, + prompt_id: promptId, + update_type: "message_chunk", + content, + }; + this.sendEnvelope("session.update", payload, guid, userId); + }; + + /** + * 发送 session.update 消息 — 工具调用开始 + * @param sessionId - 所属 Session ID + * @param promptId - 所属 Turn ID + * @param toolCall - 工具调用信息(包含 tool_call_id、title、kind、status) + * @description + * 当 Agent 开始调用某个工具时发送,通知服务端展示工具调用状态。 + */ + sendToolCall = (sessionId: string, promptId: string, toolCall: ToolCall, guid?: string, userId?: string): void => { + console.log(`${this.logPrefix} [sendToolCall] sessionId=${sessionId}, promptId=${promptId}, guid=${guid}, userId=${userId}, toolCall=${JSON.stringify(toolCall)}`); + const payload: UpdatePayload = { + session_id: sessionId, + prompt_id: promptId, + update_type: "tool_call", + tool_call: toolCall, + }; + this.sendEnvelope("session.update", payload, guid, userId); + }; + + /** + * 发送 session.update 消息 — 工具调用状态变更 + * @param sessionId - 所属 Session ID + * @param promptId - 所属 Turn ID + * @param toolCall - 更新后的工具调用信息(status 变为 completed/failed) + * @description + * 当工具执行完成或失败时发送,通知服务端更新工具调用的展示状态。 + */ + sendToolCallUpdate = (sessionId: string, promptId: string, toolCall: ToolCall, guid?: string, userId?: string): void => { + console.log(`${this.logPrefix} [sendToolCallUpdate] sessionId=${sessionId}, promptId=${promptId}, guid=${guid}, userId=${userId}, toolCall=${JSON.stringify(toolCall)}`); + const payload: UpdatePayload = { + session_id: sessionId, + prompt_id: promptId, + update_type: "tool_call_update", + tool_call: toolCall, + }; + this.sendEnvelope("session.update", payload, guid, userId); + }; + + /** + * 发送 session.promptResponse 消息 — 最终结果 + * @param payload - 包含 stop_reason、content、error 等最终结果信息 + * @description + * Agent 处理完成后发送,告知服务端本次 Turn 已结束。 + * stop_reason 可以是:end_turn(正常完成)、cancelled(被取消)、error(出错) + */ + sendPromptResponse = (payload: PromptResponsePayload, guid?: string, userId?: string): void => { + const contentPreview = payload.content ? JSON.stringify(payload.content).substring(0, 200) : '(empty)'; + console.log(`${this.logPrefix} [sendPromptResponse] sessionId=${payload.session_id}, promptId=${payload.prompt_id}, stopReason=${payload.stop_reason}, guid=${guid}, userId=${userId}, content=${contentPreview}`); + this.sendEnvelope("session.promptResponse", payload, guid, userId); + }; + + + /** + * 建立 WebSocket 连接 + * @description + * 使用 ws 库的 `new WebSocket(url)` 创建连接。 + * ws 库会在内部自动完成 TCP 握手和 WebSocket 升级协议(HTTP Upgrade)。 + * 连接是异步建立的,实际连接成功会触发 "open" 事件。 + */ + private connect = (): void => { + // url 为空时不进行连接,避免 new URL("") 抛出 TypeError + if (!this.config.url) { + console.error(`${this.logPrefix} wsUrl 未配置,跳过连接`); + this.state = "disconnected"; + return; + } + // token 为空时不进行连接,避免无效请求 + if (!this.config.token) { + console.error(`${this.logPrefix} token 为空,跳过 WebSocket 连接`); + this.state = "disconnected"; + return; + } + + this.state = "connecting"; + console.error(`${this.logPrefix} 连接配置: url=${this.config.url}, token=${this.config.token.substring(0, 6) + '...'}, guid=${this.config.guid}, userId=${this.config.userId}`); + const wsUrl = this.buildConnectionUrl(); + console.error(`${this.logPrefix} 正在连接: ${wsUrl}`); + + try { + // new WebSocket(url) 立即返回,不会阻塞 + // 连接过程在后台异步进行,通过事件通知结果 + this.ws = new WebSocket(wsUrl); + this.setupEventHandlers(); + } catch (error) { + // 同步错误(如 URL 格式非法)会在这里捕获 + // 异步连接失败(如服务端拒绝)会触发 "error" 事件 + console.error(`${this.logPrefix} 创建连接失败:`, error); + this.handleConnectionError(error instanceof Error ? error : new Error(String(error))); + } + }; + + /** + * 构建 WebSocket 连接 URL + * @description + * 使用 Node.js 内置的 `URL` 类(全局可用,无需 import)构建带查询参数的 URL。 + * `url.searchParams.set()` 会自动对参数值进行 URL 编码(encodeURIComponent), + * 避免特殊字符导致的 URL 解析问题。 + * + * 最终格式:ws://host:port/?token={token} + */ + private buildConnectionUrl = (): string => { + const url = new URL(this.config.url); + if (this.config.token) { + url.searchParams.set("token", this.config.token); + } + return url.toString(); + }; + + /** + * 注册 ws 库的事件监听器 + * @description + * ws 库使用 Node.js EventEmitter 风格的 `.on(event, handler)` 注册事件, + * 而非浏览器的 `.addEventListener(event, handler)`。 + * 两者功能相同,但回调参数类型不同: + * + * | 事件 | 浏览器原生参数 | ws 库参数 | + * |---------|----------------------|----------------------------------| + * | open | Event | 无参数 | + * | message | MessageEvent | (data: RawData, isBinary: bool) | + * | close | CloseEvent | (code: number, reason: Buffer) | + * | error | Event | (error: Error) | + * | pong | 不支持 | 无参数(ws 库特有) | + */ + private setupEventHandlers = (): void => { + if (!this.ws) return; + + this.ws.on("open", this.handleOpen); + this.ws.on("message", this.handleRawMessage); + this.ws.on("close", this.handleClose); + this.ws.on("error", this.handleError); + // "pong" 是 ws 库特有的事件,当收到服务端的 pong 控制帧时触发 + // 浏览器原生 WebSocket API 不暴露此事件 + this.ws.on("pong", this.handlePong); + }; + + // ============================================ + // 事件处理 + // ============================================ + + /** + * 处理连接建立事件 + * @description + * ws 库的 "open" 事件在 WebSocket 握手完成后触发,此时可以开始收发消息。 + * 连接成功后: + * 1. 更新状态为 "connected" + * 2. 重置重连计数器 + * 3. 重置 pong 时间戳 + * 4. 启动心跳定时器 + * 5. 启动系统唤醒检测 + * 6. 触发 onConnected 回调 + */ + private handleOpen = (): void => { + console.log(`${this.logPrefix} 连接成功`); + this.state = "connected"; + this.reconnectAttempts = 0; + this.lastPongTime = Date.now(); + this.startHeartbeat(); + this.startWakeupDetection(); + this.callbacks.onConnected?.(); + }; + + /** + * 处理收到的原始消息 + * @param data - ws 库的原始消息数据,类型为 `WebSocket.RawData` + * @description + * `WebSocket.RawData` 是 ws 库定义的联合类型:`Buffer | ArrayBuffer | Buffer[]` + * - 文本消息(text frame):通常是 Buffer 类型 + * - 二进制消息(binary frame):可能是 Buffer 或 ArrayBuffer + * + * 处理步骤: + * 1. 将 RawData 转为字符串(Buffer.toString() 默认使用 UTF-8 编码) + * 2. JSON.parse 解析为 AGPEnvelope 对象 + * 3. 检查 msg_id 去重 + * 4. 根据 method 字段分发到对应的回调 + */ + private handleRawMessage = (data: WebSocket.RawData): void => { + try { + // Buffer.toString() 默认 UTF-8 编码,等同于 data.toString("utf8") + // 如果 data 已经是 string 类型(理论上 ws 库不会这样,但做兼容处理) + const raw = typeof data === "string" ? data : data.toString(); + const envelope = JSON.parse(raw) as AGPEnvelope; + + // 消息去重:同一个 msg_id 只处理一次 + // 网络不稳定时服务端可能重发消息,通过 msg_id 避免重复处理 + if (this.processedMsgIds.has(envelope.msg_id)) { + console.log(`${this.logPrefix} 重复消息,跳过: ${envelope.msg_id}`); + return; + } + this.processedMsgIds.add(envelope.msg_id); + + console.log(`${this.logPrefix} 收到消息: method=${envelope.method}, msg_id=${envelope.msg_id}`); + + // 根据 method 字段分发消息到对应的业务处理回调 + switch (envelope.method) { + case "session.prompt": + // 下行:服务端下发用户指令,需要调用 Agent 处理 + this.callbacks.onPrompt?.(envelope as PromptMessage); + break; + case "session.cancel": + // 下行:服务端要求取消正在处理的 Turn + this.callbacks.onCancel?.(envelope as CancelMessage); + break; + default: + console.warn(`${this.logPrefix} 未知消息类型: ${envelope.method}`); + } + } catch (error) { + console.error(`${this.logPrefix} 消息解析失败:`, error, '原始数据:', data); + this.callbacks.onError?.( + error instanceof Error ? error : new Error(`消息解析失败: ${String(error)}`) + ); + } + }; + + /** + * 处理连接关闭事件 + * @param code - WebSocket 关闭状态码(RFC 6455 定义) + * 常见值: + * - 1000: 正常关闭 + * - 1001: 端点离开(如服务端重启) + * - 1006: 异常关闭(连接被强制断开,无关闭握手) + * - 1008: 策略违规(如 token 不匹配) + * @param reason - 关闭原因,ws 库中类型为 `Buffer`,需要调用 `.toString()` 转为字符串 + * @description + * 注意:ws 库的 close 事件参数与浏览器不同: + * - 浏览器:`(event: CloseEvent)` → 通过 event.code 和 event.reason 获取 + * - ws 库:`(code: number, reason: Buffer)` → 直接获取,reason 是 Buffer 需要转换 + * + * 只有在非主动关闭(state !== "disconnected")时才触发重连, + * 避免调用 stop() 后又自动重连。 + */ + private handleClose = (code: number, reason: Buffer): void => { + // Buffer.toString() 将 Buffer 转为 UTF-8 字符串 + // 如果 reason 为空 Buffer,toString() 返回空字符串,此时用 code 作为描述 + const reasonStr = reason.toString() || `code=${code}`; + console.log(`${this.logPrefix} 连接关闭: ${reasonStr}`); + this.clearHeartbeat(); + this.clearWakeupDetection(); + this.ws = null; + + // 仅在非主动关闭的情况下尝试重连 + // 主动调用 stop() 时会先将 state 设为 "disconnected",此处就不会触发重连 + if (this.state !== "disconnected") { + this.callbacks.onDisconnected?.(reasonStr); + this.scheduleReconnect(); + } + }; + + /** + * 处理 pong 控制帧 + * @description + * 当服务端收到我们发送的 ping 帧后,会自动回复一个 pong 帧。 + * ws 库会触发 "pong" 事件通知我们。 + * 记录收到 pong 的时间戳,供心跳定时器检测连接是否假死。 + * 如果长时间未收到 pong,说明连接已不可用(如电脑休眠导致 TCP 断开)。 + */ + private handlePong = (): void => { + this.lastPongTime = Date.now(); + }; + + /** + * 处理连接错误事件 + * @param error - ws 库直接传递 Error 对象(浏览器原生 API 传递的是 Event 对象) + * @description + * ws 库的 "error" 事件在以下情况触发: + * - 连接被拒绝(如服务端不可达) + * - TLS 握手失败 + * - 消息发送失败 + * 注意:error 事件之后通常会紧跟 close 事件,重连逻辑在 handleClose 中处理。 + */ + private handleError = (error: Error): void => { + console.error(`${this.logPrefix} 连接错误:`, error); + this.callbacks.onError?.(error); + }; + + /** + * 处理连接创建时的同步错误 + * @description + * 当 `new WebSocket(url)` 抛出同步异常时调用(如 URL 格式非法)。 + * 此时不会触发 "error" 和 "close" 事件,需要手动触发重连。 + */ + private handleConnectionError = (error: Error): void => { + this.callbacks.onError?.(error); + this.scheduleReconnect(); + }; + + /** + * 安排下一次重连 + * @description + * 使用指数退避(Exponential Backoff)策略计算重连延迟: + * delay = min(reconnectInterval × 1.5^(attempts-1), 30000) + * + * 例如 reconnectInterval=3000 时: + * 第 1 次:3000ms + * 第 2 次:4500ms + * 第 3 次:6750ms + * 第 4 次:10125ms + * 第 5 次:15187ms(之后趋近 30000ms 上限) + * + * 指数退避的目的:避免服务端故障时大量客户端同时重连造成雪崩效应。 + * + * `setTimeout` 是 Node.js 全局函数,在指定延迟后执行一次回调。 + * 返回值是 Timeout 对象(Node.js)或 number(浏览器), + * 需要保存以便后续调用 clearTimeout 取消。 + */ + private scheduleReconnect = (): void => { + // 检查是否超过最大重连次数(0 表示无限重连) + if ( + this.config.maxReconnectAttempts > 0 && + this.reconnectAttempts >= this.config.maxReconnectAttempts + ) { + console.error(`${this.logPrefix} 已达最大重连次数 (${this.config.maxReconnectAttempts}),停止重连`); + this.state = "disconnected"; + return; + } + + this.state = "reconnecting"; + this.reconnectAttempts++; + + // 指数退避:每次重连等待时间递增,最大 25 秒 + const delay = Math.min( + this.config.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1), + 25000 + ); + + console.log(`${this.logPrefix} ${delay}ms 后尝试第 ${this.reconnectAttempts} 次重连...`); + + // setTimeout 返回的句柄保存到 reconnectTimer, + // 以便在 stop() 或成功连接时通过 clearTimeout 取消待执行的重连 + this.reconnectTimer = setTimeout(() => { + this.reconnectTimer = null; + this.connect(); + }, delay); + }; + + /** + * 清除重连定时器 + * @description + * `clearTimeout` 是 Node.js 全局函数,取消由 setTimeout 创建的定时器。 + * 如果定时器已执行或已被取消,调用 clearTimeout 不会报错(安全操作)。 + */ + private clearReconnectTimer = (): void => { + if (this.reconnectTimer) { + clearTimeout(this.reconnectTimer); + this.reconnectTimer = null; + } + }; + + // ============================================ + // 心跳保活 + // ============================================ + + /** + * 启动心跳定时器 + * @description + * 使用 `setInterval` 定期发送 WebSocket ping 控制帧,并检测 pong 超时。 + * + * `ws.ping()` 发送 WebSocket 协议层的 ping 控制帧(opcode=0x9), + * 服务端必须自动回复 pong 帧。 + * + * Pong 超时检测: + * 如果超过 2 倍心跳间隔仍未收到 pong,判定连接已死(如休眠后 TCP 已断), + * 主动 terminate 触发 close 事件 → 自动重连。 + * + * Ping 失败处理: + * 如果 ping 发送抛异常(底层 socket 已关闭),也主动 terminate 触发重连。 + */ + private startHeartbeat = (): void => { + this.clearHeartbeat(); + this.heartbeatTimer = setInterval(() => { + if (this.ws && this.state === "connected") { + // 检测 pong 超时:超过 2 倍心跳间隔未收到 pong,判定连接已死 + const pongTimeout = this.config.heartbeatInterval * 2; + if (Date.now() - this.lastPongTime > pongTimeout) { + console.warn(`${this.logPrefix} pong 超时 (${pongTimeout}ms 未收到),判定连接已死,主动断开`); + this.ws.terminate(); + return; + } + + try { + // ws.ping() 发送 WebSocket 原生 ping 控制帧 + this.ws.ping(); + } catch { + console.warn(`${this.logPrefix} 心跳发送失败,主动断开触发重连`); + this.ws?.terminate(); + } + } + }, this.config.heartbeatInterval); + }; + + /** + * 清除心跳定时器 + * @description + * `clearInterval` 是 Node.js 全局函数,停止由 setInterval 创建的定时器。 + * 在连接关闭或主动停止时调用,避免向已断开的连接发送 ping。 + */ + private clearHeartbeat = (): void => { + if (this.heartbeatTimer) { + clearInterval(this.heartbeatTimer); + this.heartbeatTimer = null; + } + }; + + // ============================================ + // 系统唤醒检测 + // ============================================ + + /** + * 启动系统唤醒检测 + * @description + * 电脑休眠时 setInterval 会被冻结,唤醒后恢复。 + * 利用「两次 tick 之间实际经过的时间」远大于「setInterval 设定的间隔」来检测唤醒事件。 + * + * 例如:CHECK_INTERVAL = 5s,但实际两次 tick 间隔了 60s → 说明系统休眠了约 55s。 + * 此时 TCP 连接大概率已被服务端超时关闭,需要主动 terminate 触发重连。 + * + * 同时重置重连计数器,确保唤醒后有足够的重连机会。 + */ + private startWakeupDetection = (): void => { + this.clearWakeupDetection(); + this.lastTickTime = Date.now(); + + const CHECK_INTERVAL = 5000; // 每 5 秒检查一次 + const WAKEUP_THRESHOLD = 15000; // 实际间隔超过 15 秒视为休眠唤醒 + + this.wakeupCheckTimer = setInterval(() => { + const now = Date.now(); + const elapsed = now - this.lastTickTime; + this.lastTickTime = now; + + if (elapsed > WAKEUP_THRESHOLD) { + console.warn(`${this.logPrefix} 检测到系统唤醒 (tick 间隔 ${elapsed}ms,阈值 ${WAKEUP_THRESHOLD}ms)`); + // 重置重连计数器,给予唤醒后充足的重连机会 + this.reconnectAttempts = 0; + // 如果当前连接还标记为已连接,主动断开触发重连 + if (this.ws && this.state === "connected") { + console.warn(`${this.logPrefix} 唤醒后主动断开连接,触发重连`); + this.ws.terminate(); + } + } + }, CHECK_INTERVAL); + }; + + /** + * 清除系统唤醒检测定时器 + */ + private clearWakeupDetection = (): void => { + if (this.wakeupCheckTimer) { + clearInterval(this.wakeupCheckTimer); + this.wakeupCheckTimer = null; + } + }; + + // ============================================ + // 消息发送 + // ============================================ + + /** + * 发送 AGP 信封消息(内部通用方法) + * @param method - AGP 消息类型(如 "session.update"、"session.promptResponse") + * @param payload - 消息载荷,泛型 T 由调用方决定具体类型 + * @description + * 所有上行消息都通过此方法发送,统一处理: + * 1. 检查连接状态 + * 2. 构建 AGP 信封(添加 msg_id等公共字段) + * 3. JSON 序列化 + * 4. 调用 ws.send() 发送文本帧 + * + * `ws.send(data)` 是 ws 库的发送方法: + * - 传入 string:发送文本帧(opcode=0x1) + * - 传入 Buffer/ArrayBuffer:发送二进制帧(opcode=0x2) + * - 这里传入 JSON 字符串,发送文本帧 + * + * `randomUUID()` 为每条消息生成唯一 ID,服务端可用于去重和追踪。 + */ + private sendEnvelope = (method: AGPMethod, payload: T, guid?: string, userId?: string): void => { + if (!this.ws || this.state !== "connected") { + console.warn(`${this.logPrefix} 无法发送消息,当前状态: ${this.state}`); + return; + } + + const envelope: AGPEnvelope = { + msg_id: randomUUID(), + guid: guid ?? this.config.guid, + user_id: userId ?? this.config.userId, + method, + payload, + }; + + try { + const data = JSON.stringify(envelope); + // ws.send() 将字符串作为 WebSocket 文本帧发送 + this.ws.send(data); + // 截断过长的 JSON 日志,避免日志文件膨胀 + const jsonPreview = data.length > 500 ? data.substring(0, 500) + `...(truncated, total ${data.length} chars)` : data; + console.log(`${this.logPrefix} 发送消息: method=${method}, msg_id=${envelope.msg_id}, json=${jsonPreview}`); + } catch (error) { + console.error(`${this.logPrefix} 消息发送失败:`, error); + this.callbacks.onError?.( + error instanceof Error ? error : new Error(`消息发送失败: ${String(error)}`) + ); + } + }; + + // ============================================ + // 消息 ID 缓存清理 + // ============================================ + + /** + * 启动消息 ID 缓存定期清理任务 + * @description + * `processedMsgIds` 是一个 Set,会随着消息的接收不断增长。 + * 如果不清理,长时间运行后会占用大量内存(内存泄漏)。 + * + * 清理策略: + * - 每 5 分钟检查一次 + * - 当 Set 大小超过 MAX_MSG_ID_CACHE(1000)时触发清理 + * - 清理时保留最新的一半(500 条),丢弃最旧的一半 + * + * 为什么保留最新的一半而不是全部清空? + * 因为刚处理过的消息 ID 最有可能被重发,保留它们可以继续防重。 + * + * `[...this.processedMsgIds]` 将 Set 转为数组, + * Set 的迭代顺序是插入顺序,所以 slice(-500) 取的是最后插入的 500 条(最新的)。 + */ + private startMsgIdCleanup = (): void => { + this.clearMsgIdCleanup(); + this.msgIdCleanupTimer = setInterval(() => { + if (this.processedMsgIds.size > WechatAccessWebSocketClient.MAX_MSG_ID_CACHE) { + console.log(`${this.logPrefix} 清理消息 ID 缓存: ${this.processedMsgIds.size} → ${WechatAccessWebSocketClient.MAX_MSG_ID_CACHE / 2}`); + // 将 Set 转为数组(保持插入顺序),取后半部分(最新的),重建 Set + const entries = [...this.processedMsgIds]; + this.processedMsgIds.clear(); + entries.slice(-WechatAccessWebSocketClient.MAX_MSG_ID_CACHE / 2).forEach((id) => { + this.processedMsgIds.add(id); + }); + } + }, 5 * 60 * 1000); // 每 5 分钟执行一次 + }; + + /** + * 清除消息 ID 缓存清理定时器 + */ + private clearMsgIdCleanup = (): void => { + if (this.msgIdCleanupTimer) { + clearInterval(this.msgIdCleanupTimer); + this.msgIdCleanupTimer = null; + } + }; +}