diff --git a/README.md b/README.md index 4f342c4..0ef31c4 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ | SDK | 语言 | SDK 包 | Demo | 说明 | |---|---|---|---|---| | Client SDK | TypeScript | [`@autoark-ai/eva-client-sdk-ts`](https://www.npmjs.com/package/@autoark-ai/eva-client-sdk-ts) | [`browser-conversation-agent`](client-sdk/ts/browser-conversation-agent/) | 浏览器端语音、多轮对话、TTS、麦克风控制,以及可选 Emotion、Command 与摄像头图片问答 | +| Client SDK | TypeScript | [`@autoark-ai/eva-client-sdk-ts`](https://www.npmjs.com/package/@autoark-ai/eva-client-sdk-ts) | [`electron-conversation-agent`](client-sdk/ts/electron-conversation-agent/) | Electron 桌面端语音、多轮对话、TTS、麦克风控制,以及可选 Emotion、Command 与摄像头图片问答 | 机器可读目录见 [`examples.json`](examples.json)。表格链接到每个 demo 使用的 SDK package;精确版本以各 demo 的 package manifest 和 lockfile 为事实源。目录中的 `status: "release"` 表示 demo 已正式对外发布,`status: "dev"` 表示仍在开发。`verify-catalog.mjs` 会校验表格、目录与 manifest 保持一致。 diff --git a/client-sdk/README.md b/client-sdk/README.md index fad3ec2..793477c 100644 --- a/client-sdk/README.md +++ b/client-sdk/README.md @@ -5,3 +5,4 @@ 当前示例: - TypeScript:[`ts/browser-conversation-agent`](ts/browser-conversation-agent/) +- TypeScript:[`ts/electron-conversation-agent`](ts/electron-conversation-agent/) diff --git a/client-sdk/ts/electron-conversation-agent/.env.example b/client-sdk/ts/electron-conversation-agent/.env.example new file mode 100644 index 0000000..ec54049 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/.env.example @@ -0,0 +1,2 @@ +# 由 SDK 使用者(开发者)提供和管理;不要提交真实 AK。 +VITE_EVA_API_KEY=replace-with-your-gateway-api-key diff --git a/client-sdk/ts/electron-conversation-agent/.gitignore b/client-sdk/ts/electron-conversation-agent/.gitignore new file mode 100644 index 0000000..8a70fc4 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/.gitignore @@ -0,0 +1,4 @@ +.env +dist/ +dist-electron/ +node_modules/ diff --git a/client-sdk/ts/electron-conversation-agent/README.md b/client-sdk/ts/electron-conversation-agent/README.md new file mode 100644 index 0000000..009f3cd --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/README.md @@ -0,0 +1,117 @@ +# EVA Client SDK · TypeScript Electron Conversation Agent + +这是 EVA Client SDK 的 TypeScript Electron 桌面 demo,展示多轮语音对话、实时转写、TTS、麦克风控制、文本输入、emotion 旁路分类、command 调用,以及默认关闭的摄像头图片问答。 + +Electron 渲染进程运行在 Chromium 中,因此 demo 直接复用与浏览器 demo 相同的渲染层与 `@autoark-ai/eva-client-sdk-ts/browser` Media SPI helper。渲染进程只从 public npm package 的 `.`、`./spi` 和 `./browser` 三个公共入口导入,不依赖 SDK 源码、workspace link、internal seam 或本地 tarball。SDK 的创建与启动主路径集中在 `src/sdk-usage.ts`;`src/main.ts` 只负责页面交互、运行时 AK 输入、状态和事件展示。 + +Electron 主进程与预加载脚本放在独立的 `electron/` 目录:`electron/main.ts` 创建窗口、加载渲染进程并在 macOS 上申请媒体权限;`electron/preload.ts` 在启用 `contextIsolation` 的隔离世界里只暴露少量只读运行信息。主进程不参与任何 SDK 调用。 + +## 环境要求 + +- Node.js `>=22` +- macOS / Windows / Linux 桌面环境,并允许应用访问麦克风与摄像头 +- 开发者自行管理的 EVA Gateway AK + +## 项目结构 + +```text +electron-conversation-agent/ +├── index.html # 渲染进程页面 +├── src/ # 渲染进程:SDK 接入与页面交互(Chromium 中运行) +│ ├── main.ts # 页面层:DOM、AK 弹窗、事件展示 +│ ├── sdk-usage.ts # SDK 创建/启动主路径 +│ └── styles.css +├── electron/ # 主进程与预加载脚本(Node 中运行) +│ ├── main.ts +│ └── preload.ts +├── vite.config.ts # 渲染进程由 Vite 构建(base: "./") +├── tsconfig.json # 渲染进程 TS 配置 +└── tsconfig.electron.json # 主进程 / 预加载 TS 配置(编译为 CommonJS) +``` + +## 本地运行 + +先安装依赖: + +```bash +npm ci +``` + +> 依赖安装时,Electron 会为当前平台下载一个专属运行时二进制(约 90MB)。若处于受限网络或代理环境导致下载失败(`electron --version` 报 `Electron failed to install correctly`),可用官方的 `ELECTRON_MIRROR` 环境变量指向可访问的下载源后重装,详见 [Electron 安装文档](https://www.electronjs.org/docs/latest/tutorial/installation#mirror)。 + +`npm run dev` 会并行启动 Vite 开发服务器并在其就绪后拉起 Electron 窗口(主进程通过 `VITE_DEV_SERVER_URL` 加载开发服务器)。 + +### 页面输入 AK + +```bash +npm run dev +``` + +窗口会在启动会话时要求输入 Gateway AK。手工输入的 AK 只保存在当前渲染进程内存中,关闭窗口后清除。 + +### 使用项目 .env + +复制示例文件、填写 AK 后启动: + +```bash +cp .env.example .env +npm run dev +``` + +### 使用外部 key 文件 + +key 文件可以位于仓库外,内容为: + +```dotenv +EVA_GATEWAY_API_KEY=akxxx +``` + +从 demo 目录启动,并传入文件路径: + +```bash +npm run dev:key-file -- /absolute/path/to/eva-key.env +``` + +`dev:key-file` 会读取所需变量并适配当前 demo,不会复制 key 文件、生成 `.env` 或输出 AK。 + +仓库不得提交真实 AK。SDK 不会把 AK 写入事件、错误或消息,但桌面应用的开发者仍须自行决定最终应用如何管理凭证。 + +## 媒体权限 + +渲染进程通过 `getUserMedia` 采集麦克风与摄像头。主进程为窗口注册了 `setPermissionRequestHandler`,只放行 `media` 权限请求;在 macOS 上还会在启动时调用 `systemPreferences.askForMediaAccess` 申请系统级麦克风与摄像头授权。首次运行时请在系统弹窗中允许,否则采集会失败。 + +## 可选能力:Emotion 与 Command + +Emotion 和 Command 是彼此独立的 opt-in 能力,也都不是基础 Agent 的必选项。省略它们不会影响文本或语音会话、ASR、LLM、TTS、摄像头以及消息历史。 + +| 能力 | Demo 的启用方式 | 省略配置后的行为 | 运行时事件 | +|---|---|---|---| +| Emotion | `emotion: { enabled: true, labels: ["happy", "sad"] }` | 不发起旁路 emotion 分类 | 不产生 `emotion.detected` | +| Command | `commands: { registrations, maxCallsPerTurn: 3 }` | 不向 LLM 暴露 command definitions,也不执行 handler | 不产生 `command.called`、`command.completed` 或 `command.failed` | + +Demo 注册了两个可实际触发的 command: + +- “现在几点?”触发 `show_current_time`,返回设备本地时间。 +- “把页面切换为深色主题”触发 `set_page_theme`,将页面切换为深色;也可以要求切回浅色。 + +这里的 custom emotion labels 会完整替换 SDK 默认业务标签,而不是在默认集合上追加;SDK 会在缺失时自动补充唯一的 `unknown`。`AgentEvent` 在类型层始终表示完整的公共事件目录,即使某个 Agent 实例没有启用 Emotion 或 Command,使用穷尽 `switch` 的消费者仍应保留这些事件分支。 + +## 生产构建 + +```bash +npm run build # typecheck → vite build(渲染进程)→ tsc(主进程/预加载) +npm start # 用 Electron 加载构建产物运行 +``` + +`vite build` 使用相对资产路径输出到 `dist/`,主进程通过 `loadFile` 直接加载 `dist/index.html`;`tsc -p tsconfig.electron.json` 将主进程与预加载脚本编译到 `dist-electron/`。本 demo 只覆盖到本地运行与构建;如需分发安装包,可在此基础上引入 electron-builder 等打包工具。 + +## SDK 兼容性 + +精确 SDK 版本由 `package.json` 与 `package-lock.json` 共同锁定。升级 SDK 时必须重新运行: + +```bash +npm install @autoark-ai/eva-client-sdk-ts@ --save-exact +npm run build +``` + +升级后的 demo 需要重新完成真实桌面窗口下的麦克风、TTS、摄像头和 Stop 释放回归后,才能创建新的已验证 release/tag。 diff --git a/client-sdk/ts/electron-conversation-agent/electron/main.ts b/client-sdk/ts/electron-conversation-agent/electron/main.ts new file mode 100644 index 0000000..7da7670 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/electron/main.ts @@ -0,0 +1,67 @@ +import { app, BrowserWindow, session, systemPreferences } from "electron"; +import path from "node:path"; + +/** + * Electron 主进程。 + * + * 只负责创建窗口、加载渲染进程(dev 用 Vite 开发服务器,生产加载 vite build 产物), + * 以及在 macOS 上向系统申请麦克风/摄像头权限并对渲染进程的媒体权限请求放行。 + * EVA 会话本身完全运行在渲染进程里(见 src/sdk-usage.ts),主进程不参与 SDK 调用。 + */ + +// dev 模式由 npm run dev 注入;生产构建下为 undefined,改为加载本地 dist。 +const devServerUrl = process.env.VITE_DEV_SERVER_URL; + +function createWindow(): void { + const window = new BrowserWindow({ + width: 960, + height: 860, + minWidth: 480, + minHeight: 640, + backgroundColor: "#0b0b10", + autoHideMenuBar: true, + webPreferences: { + preload: path.join(__dirname, "preload.js"), + contextIsolation: true, + nodeIntegration: false, + // 渲染进程需要 getUserMedia 采集麦克风/摄像头,沙箱下仍可用。 + sandbox: true, + }, + }); + + if (devServerUrl !== undefined) { + void window.loadURL(devServerUrl); + window.webContents.openDevTools({ mode: "detach" }); + } else { + void window.loadFile(path.join(__dirname, "..", "dist", "index.html")); + } +} + +async function requestMediaAccess(): Promise { + // macOS 首次采集前需要显式申请系统权限,否则 getUserMedia 会静默失败。 + if (process.platform !== "darwin") return; + try { + await systemPreferences.askForMediaAccess("microphone"); + await systemPreferences.askForMediaAccess("camera"); + } catch { + // 用户拒绝时继续启动;渲染进程会在 error 事件里反映不可用状态。 + } +} + +void app.whenReady().then(async () => { + // 放行渲染进程发起的 media(麦克风/摄像头)权限请求,其余一律拒绝。 + session.defaultSession.setPermissionRequestHandler((_webContents, permission, callback) => { + callback(permission === "media"); + }); + + await requestMediaAccess(); + createWindow(); + + app.on("activate", () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); + +app.on("window-all-closed", () => { + if (process.platform !== "darwin") app.quit(); +}); diff --git a/client-sdk/ts/electron-conversation-agent/electron/preload.ts b/client-sdk/ts/electron-conversation-agent/electron/preload.ts new file mode 100644 index 0000000..7d7c403 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/electron/preload.ts @@ -0,0 +1,17 @@ +import { contextBridge } from "electron"; + +/** + * 预加载脚本,在启用 contextIsolation 的隔离世界里运行。 + * + * 本 demo 的渲染进程直接通过公开 SDK 与 EVA 通信,不需要主进程特权能力, + * 因此这里只暴露少量只读的运行环境信息。如果后续渲染进程需要访问主进程能力, + * 在这里通过 contextBridge 显式、最小化地暴露,而不是打开 nodeIntegration。 + */ +contextBridge.exposeInMainWorld("evaElectron", { + platform: process.platform, + versions: { + electron: process.versions.electron, + chrome: process.versions.chrome, + node: process.versions.node, + }, +}); diff --git a/client-sdk/ts/electron-conversation-agent/index.html b/client-sdk/ts/electron-conversation-agent/index.html new file mode 100644 index 0000000..56b1140 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/index.html @@ -0,0 +1,163 @@ + + + + + + + EVA Electron Conversation Agent + + +
+
+
+ +
+

EVA Voice

+

语音对话

+
+
+

@autoark-ai/eva-client-sdk-ts

+
+ +
+
+

+ + 未启动 + +

+

准备好聊聊了吗?

+

启动后直接开口,EVA 会实时听见并回应你。

+
+ + + +
+ + +
+
+ +
+
+

对话设备

+

会话中也可以随时调整

+
+
+ + + +
+
+ +
+
+
+

Conversation

+

对话记录

+
+ 仅保留在当前会话 +
+
    +
    + +

    对话开始后,双方内容会显示在这里

    +
    + +
    +
    +

    你正在说

    +

    等待语音输入

    +
    +
    +

    EVA 正在回应

    +

    等待开始对话

    +
    +
    + +
    + + + +
    +
    + +
    + + 开发者诊断 + 事件、设备与 latency + +
    +
    +
    +

    状态日志

    + +
    + +
    +
    +

    运行状态

    +
    +
    麦克风
    未请求
    +
    摄像头
    默认关闭
    +
    打断
    +
    情绪
    +
    Command
    +
    错误
    +
    +
    暂无 latency
    +
    +
    +
    +
    + + +
    +

    输入 Gateway AK

    +

    AK 只保存在当前页面内存中,刷新页面后会清除。

    + + + +
    + + +
    +
    +
    + + + diff --git a/client-sdk/ts/electron-conversation-agent/package-lock.json b/client-sdk/ts/electron-conversation-agent/package-lock.json new file mode 100644 index 0000000..39360f7 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/package-lock.json @@ -0,0 +1,2731 @@ +{ + "name": "eva-client-sdk-ts-electron-conversation-agent", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "eva-client-sdk-ts-electron-conversation-agent", + "version": "0.0.0", + "dependencies": { + "@autoark-ai/eva-client-sdk-ts": "1.0.0" + }, + "devDependencies": { + "concurrently": "^9.1.0", + "cross-env": "^7.0.3", + "electron": "^33.4.11", + "typescript": "^5.6.0", + "vite": "^8.1.4", + "wait-on": "^8.0.1" + } + }, + "node_modules/@alexanderolsen/libsamplerate-js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@alexanderolsen/libsamplerate-js/-/libsamplerate-js-2.1.2.tgz", + "integrity": "sha512-pIXQDX/DZIgz6pKInUddDd6Tnq/s2E9g4ZITkKX60kxM/nAuZcxYa/z0y/jwJbjyp/oKe+8/qHLSqMzQ18xSiQ==", + "license": "MIT" + }, + "node_modules/@autoark-ai/eva-client-sdk-ts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@autoark-ai/eva-client-sdk-ts/-/eva-client-sdk-ts-1.0.0.tgz", + "integrity": "sha512-X8uFxUefbYs2s4wFKuitCT1tmb3M1V3AxVOmw/Uev7DUvJY3bECJZqKChIie/75ZYVUsYuAz0k9AjU7HuhUKqw==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@alexanderolsen/libsamplerate-js": "2.1.2", + "onnxruntime-web": "1.26.0" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@emnapi/core": { + "version": "2.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz", + "integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "2.0.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "2.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz", + "integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz", + "integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@hapi/address": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", + "integrity": "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/formula": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-3.0.2.tgz", + "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/hoek": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", + "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/pinpoint": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.1.tgz", + "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/tlds": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@hapi/tlds/-/tlds-1.1.7.tgz", + "integrity": "sha512-MgNjRwy9Ti92yVAixLmDc8dd1bJIKwO9qlWCfFQRwRmUEDPQHYn4G6hwPFvFGUTzAa0FsS+inMjLin7GnyBRhA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/topo": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", + "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", + "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.142.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz", + "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "license": "BSD-3-Clause" + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.1.tgz", + "integrity": "sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.1.tgz", + "integrity": "sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.1.tgz", + "integrity": "sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.1.tgz", + "integrity": "sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.1.tgz", + "integrity": "sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.1.tgz", + "integrity": "sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.1.tgz", + "integrity": "sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.1.tgz", + "integrity": "sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.1.tgz", + "integrity": "sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.1.tgz", + "integrity": "sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.1.tgz", + "integrity": "sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.1.tgz", + "integrity": "sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.1.tgz", + "integrity": "sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "2.0.0-alpha.3", + "@emnapi/runtime": "2.0.0-alpha.3", + "@napi-rs/wasm-runtime": "^1.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.1.tgz", + "integrity": "sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.1.tgz", + "integrity": "sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "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/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concurrently": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.4.tgz", + "integrity": "sha512-TZ0CEhyzvFjgtAvHTusDMgj7wNdihCh7LLLrzdUOXIhdlnL2JBBGA9eJxR24rtqgmdjh3OA3hrN1rCHj6HM8qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.9.0", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron": { + "version": "33.4.11", + "resolved": "https://registry.npmjs.org/electron/-/electron-33.4.11.tgz", + "integrity": "sha512-xmdAs5QWRkInC7TpXGNvzo/7exojubk+72jn1oJL7keNeIlw7xNglf8TGtJtkR4rWC5FJq0oXiIXPS9BcK2Irg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^20.9.0", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "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/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "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/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/flatbuffers": { + "version": "25.9.23", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", + "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", + "license": "Apache-2.0" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "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.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "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.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/guid-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", + "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/joi": { + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-18.2.3.tgz", + "integrity": "sha512-N5A3KTWQpPWT4ExxxPlUx7WmykGXRzhNidWhV41d6Abu9YfI2NyWCJuxdPnslJCPWtbRpSVOWSnSS6GakLM/Rg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/address": "^5.1.1", + "@hapi/formula": "^3.0.2", + "@hapi/hoek": "^11.0.7", + "@hapi/pinpoint": "^2.0.1", + "@hapi/tlds": "^1.1.1", + "@hapi/topo": "^6.0.2", + "@standard-schema/spec": "^1.1.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onnxruntime-common": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.26.0.tgz", + "integrity": "sha512-qVyMR4lcWgbkc4getFV+GQijsTnbg/siteoqcDwa3sI/LxbrMSNw4ePyvCq/ymdQaRomCA7YuWmhzsswxvymdw==", + "license": "MIT" + }, + "node_modules/onnxruntime-web": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.26.0.tgz", + "integrity": "sha512-LbRr/8zZt2xilI2smrVQGGKINo0U46i8qJp+UXyMBGfqN7KjnH1BiwCwLwyNIVV4i9CKFv7Sf4PwLKWnT8/bEA==", + "license": "MIT", + "dependencies": { + "flatbuffers": "^25.1.24", + "guid-typescript": "^1.0.9", + "long": "^5.2.3", + "onnxruntime-common": "1.26.0", + "platform": "^1.3.6", + "protobufjs": "^7.2.4" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/rolldown": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.1.tgz", + "integrity": "sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.142.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.2.1", + "@rolldown/binding-darwin-arm64": "1.2.1", + "@rolldown/binding-darwin-x64": "1.2.1", + "@rolldown/binding-freebsd-x64": "1.2.1", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.1", + "@rolldown/binding-linux-arm64-gnu": "1.2.1", + "@rolldown/binding-linux-arm64-musl": "1.2.1", + "@rolldown/binding-linux-ppc64-gnu": "1.2.1", + "@rolldown/binding-linux-s390x-gnu": "1.2.1", + "@rolldown/binding-linux-x64-gnu": "1.2.1", + "@rolldown/binding-linux-x64-musl": "1.2.1", + "@rolldown/binding-openharmony-arm64": "1.2.1", + "@rolldown/binding-wasm32-wasi": "1.2.1", + "@rolldown/binding-win32-arm64-msvc": "1.2.1", + "@rolldown/binding-win32-x64-msvc": "1.2.1" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz", + "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/vite": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz", + "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.23", + "rolldown": "~1.2.0", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/wait-on": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.5.tgz", + "integrity": "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.12.1", + "joi": "^18.0.1", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.2" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "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.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/client-sdk/ts/electron-conversation-agent/package.json b/client-sdk/ts/electron-conversation-agent/package.json new file mode 100644 index 0000000..b6150cb --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/package.json @@ -0,0 +1,29 @@ +{ + "name": "eva-client-sdk-ts-electron-conversation-agent", + "private": true, + "version": "0.0.0", + "description": "EVA Client SDK TypeScript Electron conversation agent demo.", + "main": "dist-electron/main.js", + "scripts": { + "dev": "concurrently -k -n vite,electron -c cyan,magenta \"npm:dev:renderer\" \"npm:dev:electron\"", + "dev:renderer": "vite --host 127.0.0.1 --port 5273 --strictPort", + "dev:electron": "wait-on tcp:127.0.0.1:5273 && npm run build:electron && cross-env VITE_DEV_SERVER_URL=http://127.0.0.1:5273 electron .", + "dev:key-file": "node scripts/run-npm-demo-with-key-file.mjs", + "build:electron": "tsc -p tsconfig.electron.json", + "typecheck": "tsc --noEmit && tsc -p tsconfig.electron.json --noEmit", + "build": "npm run typecheck && vite build && npm run build:electron", + "postbuild": "node scripts/verify-dist-paths.mjs", + "start": "electron ." + }, + "dependencies": { + "@autoark-ai/eva-client-sdk-ts": "1.0.0" + }, + "devDependencies": { + "concurrently": "^9.1.0", + "cross-env": "^7.0.3", + "electron": "^33.4.11", + "typescript": "^5.6.0", + "vite": "^8.1.4", + "wait-on": "^8.0.1" + } +} diff --git a/client-sdk/ts/electron-conversation-agent/scripts/run-npm-demo-with-key-file.mjs b/client-sdk/ts/electron-conversation-agent/scripts/run-npm-demo-with-key-file.mjs new file mode 100644 index 0000000..9fb1e07 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/scripts/run-npm-demo-with-key-file.mjs @@ -0,0 +1,155 @@ +#!/usr/bin/env node + +import { spawnSync } from "node:child_process"; +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { pathToFileURL } from "node:url"; + +export const keyMappings = Object.freeze([ + Object.freeze({ + source: "EVA_GATEWAY_API_KEY", + target: "VITE_EVA_API_KEY", + }), +]); + +export function parseKeyFile(contents, mappings = keyMappings) { + if (typeof contents !== "string") { + throw new TypeError("key file contents must be UTF-8 text"); + } + validateMappings(mappings); + + const expectedSources = new Set(mappings.map((mapping) => mapping.source)); + const collectedValues = new Map(mappings.map((mapping) => [mapping.source, []])); + const lines = contents.replace(/^\uFEFF/, "").split(/\r?\n/); + for (const rawLine of lines) { + const line = rawLine.trim(); + if (line.length === 0 || line.startsWith("#")) continue; + + const assignment = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line); + const source = assignment?.[1]; + if (source === undefined || !expectedSources.has(source)) continue; + + let value = assignment[2].trim(); + const first = value[0]; + const last = value.at(-1); + if ((first === "\"" || first === "'") && last === first) { + value = value.slice(1, -1); + } else if (first === "\"" || first === "'" || last === "\"" || last === "'") { + throw new Error(source + " has unmatched quotes"); + } + if (value.length === 0 || /\s/.test(value)) { + throw new Error(source + " must be a non-empty value without whitespace"); + } + collectedValues.get(source).push(value); + } + + const parsedValues = {}; + for (const mapping of mappings) { + const values = collectedValues.get(mapping.source); + if (values.length === 0) { + throw new Error("key file is missing " + mapping.source); + } + if (values.length > 1) { + throw new Error("key file contains duplicate " + mapping.source + " entries"); + } + parsedValues[mapping.source] = values[0]; + } + return parsedValues; +} + +export function createRuntimeEnvironment(values, mappings = keyMappings, baseEnvironment = process.env) { + validateMappings(mappings); + const environment = { ...baseEnvironment }; + for (const mapping of mappings) { + delete environment[mapping.source]; + environment[mapping.target] = values[mapping.source]; + } + return environment; +} + +export async function readKeyFile(keyFilePath, mappings = keyMappings) { + const contents = await readFile(resolve(keyFilePath), "utf8"); + return parseKeyFile(contents, mappings); +} + +export function createNpmDevArgs(viteArgs = []) { + const npmArgs = ["run", "dev"]; + if (viteArgs.length > 0) npmArgs.push("--", ...viteArgs); + return npmArgs; +} + +export function createNpmInvocation( + npmArgs, + { + platform = process.platform, + nodeExecutable = process.execPath, + npmCliPath = process.env.npm_execpath, + } = {}, +) { + if (platform !== "win32") { + return { command: "npm", args: npmArgs }; + } + if (typeof npmCliPath !== "string" || npmCliPath.length === 0) { + throw new Error( + "npm CLI path is unavailable; start this launcher with npm run dev:key-file", + ); + } + return { + command: nodeExecutable, + args: [npmCliPath, ...npmArgs], + }; +} + +export async function main(args = process.argv.slice(2)) { + const [keyFilePath, ...viteArgs] = args; + if (keyFilePath === undefined) { + throw new Error("usage: npm run dev:key-file -- /path/to/key-file [vite options]"); + } + + const values = await readKeyFile(keyFilePath); + const npmArgs = createNpmDevArgs(viteArgs); + const npmInvocation = createNpmInvocation(npmArgs); + + console.log("Starting demo with " + keyMappings.length + " mapped key(s) from key file (values hidden)."); + const result = spawnSync(npmInvocation.command, npmInvocation.args, { + cwd: process.cwd(), + env: createRuntimeEnvironment(values), + stdio: "inherit", + }); + if (result.error !== undefined) throw result.error; + process.exitCode = result.status ?? 1; +} + +function validateMappings(mappings) { + if (!Array.isArray(mappings) || mappings.length === 0) { + throw new TypeError("key mappings must be a non-empty array"); + } + const sources = new Set(); + const targets = new Set(); + for (const mapping of mappings) { + if ( + typeof mapping?.source !== "string" + || typeof mapping.target !== "string" + || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(mapping.source) + || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(mapping.target) + ) { + throw new TypeError("key mappings must contain valid source and target environment variable names"); + } + if (sources.has(mapping.source) || targets.has(mapping.target)) { + throw new Error("key mappings must use unique source and target names"); + } + sources.add(mapping.source); + targets.add(mapping.target); + } +} + +const entryPath = process.argv[1]; +if (entryPath !== undefined && import.meta.url === pathToFileURL(resolve(entryPath)).href) { + try { + await main(); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + console.error("Key-file launch failed: " + message); + process.exitCode = 1; + } +} diff --git a/client-sdk/ts/electron-conversation-agent/scripts/run-npm-demo-with-key-file.test.mjs b/client-sdk/ts/electron-conversation-agent/scripts/run-npm-demo-with-key-file.test.mjs new file mode 100644 index 0000000..1bc6a02 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/scripts/run-npm-demo-with-key-file.test.mjs @@ -0,0 +1,134 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + createNpmDevArgs, + createNpmInvocation, + createRuntimeEnvironment, + keyMappings, + parseKeyFile, +} from "./run-npm-demo-with-key-file.mjs"; + +test("forwards custom Vite options after npm's argument separator", () => { + assert.deepEqual(createNpmDevArgs(["--port", "4173"]), [ + "run", + "dev", + "--", + "--port", + "4173", + ]); +}); + +test("launches npm directly on non-Windows platforms", () => { + const npmArgs = createNpmDevArgs(["--port", "4173"]); + + assert.deepEqual(createNpmInvocation(npmArgs, { platform: "linux" }), { + command: "npm", + args: ["run", "dev", "--", "--port", "4173"], + }); +}); + +test("launches npm's JavaScript CLI through Node on Windows", () => { + const npmArgs = createNpmDevArgs(["--port", "4173"]); + + assert.deepEqual(createNpmInvocation(npmArgs, { + platform: "win32", + nodeExecutable: "C:\\Program Files\\nodejs\\node.exe", + npmCliPath: "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js", + }), { + command: "C:\\Program Files\\nodejs\\node.exe", + args: [ + "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js", + "run", + "dev", + "--", + "--port", + "4173", + ], + }); +}); + +test("requires npm's JavaScript CLI path for the Windows launcher", () => { + assert.throws( + () => createNpmInvocation(["run", "dev"], { + platform: "win32", + npmCliPath: undefined, + }), + /start this launcher with npm run dev:key-file/, + ); +}); + +test("parses the standard key file without exposing unrelated fields", () => { + const contents = [ + "# managed outside the repository", + "OTHER_VALUE=ignored", + "EVA_GATEWAY_API_KEY=ak-test-value", + "", + ].join("\n"); + + assert.deepEqual(parseKeyFile(contents), { + EVA_GATEWAY_API_KEY: "ak-test-value", + }); +}); + +test("accepts unquoted, double-quoted, and single-quoted values", () => { + const assignments = [ + "EVA_GATEWAY_API_KEY=ak-test-value", + "EVA_GATEWAY_API_KEY=\"ak-test-value\"", + "EVA_GATEWAY_API_KEY='ak-test-value'", + ]; + + for (const assignment of assignments) { + assert.deepEqual(parseKeyFile(assignment), { + EVA_GATEWAY_API_KEY: "ak-test-value", + }); + } +}); + +test("rejects missing, duplicate, empty, whitespace, and unmatched-quote values", () => { + assert.throws(() => parseKeyFile("OTHER_VALUE=ignored"), /missing EVA_GATEWAY_API_KEY/); + assert.throws( + () => parseKeyFile("EVA_GATEWAY_API_KEY=ak-one\nEVA_GATEWAY_API_KEY=ak-two"), + /duplicate EVA_GATEWAY_API_KEY/, + ); + assert.throws(() => parseKeyFile("EVA_GATEWAY_API_KEY="), /non-empty/); + assert.throws(() => parseKeyFile("EVA_GATEWAY_API_KEY=ak has spaces"), /without whitespace/); + assert.throws(() => parseKeyFile("EVA_GATEWAY_API_KEY=\"ak-value"), /unmatched quotes/); +}); + +test("maps the standard key to Vite without retaining the source variable", () => { + const environment = createRuntimeEnvironment( + { EVA_GATEWAY_API_KEY: "ak-secret" }, + keyMappings, + { + PATH: "/usr/bin", + EVA_GATEWAY_API_KEY: "stale-value", + }, + ); + + assert.deepEqual(environment, { + PATH: "/usr/bin", + VITE_EVA_API_KEY: "ak-secret", + }); +}); + +test("parses and maps multiple configured keys", () => { + const mappings = [ + { source: "EVA_GATEWAY_API_KEY", target: "VITE_EVA_API_KEY" }, + { source: "EVA_SECONDARY_TOKEN", target: "VITE_EVA_SECONDARY_TOKEN" }, + ]; + const values = parseKeyFile( + "EVA_GATEWAY_API_KEY=ak-primary\nEVA_SECONDARY_TOKEN=token-secondary\n", + mappings, + ); + + assert.deepEqual(values, { + EVA_GATEWAY_API_KEY: "ak-primary", + EVA_SECONDARY_TOKEN: "token-secondary", + }); + assert.deepEqual(createRuntimeEnvironment(values, mappings, { PATH: "/usr/bin" }), { + PATH: "/usr/bin", + VITE_EVA_API_KEY: "ak-primary", + VITE_EVA_SECONDARY_TOKEN: "token-secondary", + }); +}); diff --git a/client-sdk/ts/electron-conversation-agent/scripts/verify-dist-paths.mjs b/client-sdk/ts/electron-conversation-agent/scripts/verify-dist-paths.mjs new file mode 100644 index 0000000..b62c3d3 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/scripts/verify-dist-paths.mjs @@ -0,0 +1,16 @@ +import { readFile } from "node:fs/promises"; + +const html = await readFile(new URL("../dist/index.html", import.meta.url), "utf8"); +const rootRelativeAsset = html.match(/(?:src|href)=(['"])\/assets\//); + +if (rootRelativeAsset) { + throw new Error( + "dist/index.html contains a root-relative /assets/ URL; static subpath deployment would return 404", + ); +} + +if (!html.includes("./assets/")) { + throw new Error("dist/index.html does not contain relative ./assets/ URLs"); +} + +console.log("electron demo dist uses subpath-safe relative asset URLs"); diff --git a/client-sdk/ts/electron-conversation-agent/src/main.ts b/client-sdk/ts/electron-conversation-agent/src/main.ts new file mode 100644 index 0000000..b2410f3 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/src/main.ts @@ -0,0 +1,466 @@ +import { + startEvaAgent, + type AgentEvent, + type EvaVoiceDialogueAgent, +} from "./sdk-usage"; +import "./styles.css"; + +/** + * Demo 页面层。 + * + * 可复制的 SDK 创建/启动主路径集中在 ./sdk-usage.ts;本文件负责 DOM、AK 弹窗、 + * 按钮状态、事件展示和日志,并通过 SDK 的 public Facade 驱动会话。 + */ + +// Demo 页面状态与 DOM wiring。 +const environmentApiKey = normalizeApiKey(import.meta.env.VITE_EVA_API_KEY); +let manualApiKey: string | undefined; +let agent: EvaVoiceDialogueAgent | undefined; +let unsubscribe: (() => void) | undefined; +let audioInputEnabled = true; +let ttsEnabled = true; +let cameraEnabled = false; +let mediaControlsLocked = false; +let callStartedAt: number | undefined; +let callTimer: number | undefined; + +type VoiceStageState = + | "idle" + | "starting" + | "ready" + | "listening" + | "processing" + | "speaking" + | "error"; + +const startButton = element("start"); +const stopButton = element("stop"); +const audioInputButton = element("audio-input"); +const ttsButton = element("tts"); +const cameraButton = element("camera"); +const form = element("text-form"); +const textInput = element("text"); +const submitButton = form.querySelector("button[type=submit]")!; +const clearLogButton = element("clear-log"); +const apiKeyDialog = element("api-key-dialog"); +const apiKeyForm = element("api-key-form"); +const apiKeyInput = element("api-key-input"); +const apiKeyError = element("api-key-error"); +const apiKeyCancelButton = element("api-key-cancel"); +const voiceStage = element("voice-stage"); +const conversationEmpty = element("conversation-empty"); +const callDuration = element("call-duration"); + +startButton.addEventListener("click", () => void start()); +stopButton.addEventListener("click", () => void stop()); +audioInputButton.addEventListener("click", () => void toggleAudioInput()); +ttsButton.addEventListener("click", () => void toggleTts()); +cameraButton.addEventListener("click", () => void toggleCamera()); +form.addEventListener("submit", (event) => void submit(event)); +clearLogButton.addEventListener("click", () => { + element("activity-log").value = ""; +}); +apiKeyForm.addEventListener("submit", (event) => { + event.preventDefault(); + if (normalizeApiKey(apiKeyInput.value) === undefined) { + apiKeyError.textContent = "请输入有效的 Gateway AK"; + apiKeyInput.focus(); + return; + } + apiKeyDialog.close("confirm"); +}); +apiKeyCancelButton.addEventListener("click", () => apiKeyDialog.close("cancel")); + +async function start(): Promise { + if (agent !== undefined) return; + setBusy(true); + try { + const apiKey = await resolveApiKey(); + if (apiKey === undefined) { + setText("status", "未启动;未提供 AK"); + setVoiceState("idle", "准备好聊聊了吗?", "启动后直接开口,EVA 会实时听见并回应你。"); + return; + } + setMediaControlsLocked(true); + setText("status", "启动中…"); + setVoiceState("starting", "正在连接 EVA", "请稍候,我们正在准备麦克风和语音通道。"); + setText("microphone", audioInputEnabled ? "请求权限中…" : "已禁用"); + + /** + * ======================================================================== + * SDK 接入入口:从这里进入 sdk-usage.ts + * Media SPI 组合、Agent 创建、事件订阅与 start() 都集中在 startEvaAgent()。 + * ======================================================================== + */ + const started = await startEvaAgent({ + apiKey, + audioInputEnabled, + ttsEnabled, + cameraEnabled, + onEvent: handleEvent, + }); + agent = started.agent; + unsubscribe = started.unsubscribe; + setText("status", "已接通"); + setVoiceState( + audioInputEnabled ? "ready" : "idle", + audioInputEnabled ? "通话已接通" : "语音输入已关闭", + audioInputEnabled ? "直接开口即可,EVA 在听。" : "打开麦克风,或使用下方文字输入。", + ); + setText("microphone", audioInputEnabled ? "已连接" : "已禁用"); + setText("camera-status", cameraEnabled ? "持续连接;说话时采一张图" : "默认关闭"); + setSessionConnected(true); + submitButton.disabled = false; + setMediaControlsLocked(false); + } catch (error) { + setText("status", "启动失败"); + setVoiceState("error", "连接没有成功", "请检查 AK、网络与设备权限后重试。"); + setText("microphone", "不可用"); + setText("error", error instanceof Error ? error.message : String(error)); + unsubscribe?.(); + unsubscribe = undefined; + agent = undefined; + setSessionConnected(false); + setMediaControlsLocked(false); + } finally { + setBusy(false); + startButton.disabled = agent !== undefined; + } +} + +// Demo-only:允许 Electron 渲染进程在启动时取得 AK,不属于 SDK API。 +async function resolveApiKey(): Promise { + if (environmentApiKey !== undefined) return environmentApiKey; + if (manualApiKey !== undefined) return manualApiKey; + const candidate = await requestManualApiKey(); + if (candidate !== undefined) manualApiKey = candidate; + return candidate; +} + +function requestManualApiKey(): Promise { + apiKeyInput.value = ""; + apiKeyError.textContent = ""; + apiKeyDialog.returnValue = ""; + + return new Promise((resolve) => { + apiKeyDialog.addEventListener("close", () => { + const candidate = apiKeyDialog.returnValue === "confirm" + ? normalizeApiKey(apiKeyInput.value) + : undefined; + apiKeyInput.value = ""; + resolve(candidate); + }, { once: true }); + apiKeyDialog.showModal(); + apiKeyInput.focus(); + }); +} + +function normalizeApiKey(value: string | undefined): string | undefined { + const normalized = value?.trim(); + return normalized === undefined + || normalized.length === 0 + || normalized.startsWith("replace-") + ? undefined + : normalized; +} + +// Demo 控件:分别调用 SDK public Facade 的 stop / media control / submitText。 +async function stop(): Promise { + const current = agent; + if (current === undefined) return; + agent = undefined; + submitButton.disabled = true; + stopButton.disabled = true; + startButton.disabled = true; + stopCallTimer(); + setMediaControlsLocked(true); + setText("status", "停止中…"); + setVoiceState("processing", "正在结束会话", "EVA 正在释放本次会话使用的设备。"); + try { + await current.stop(); + renderMessages(current); + setText("status", "通话已结束;再次启动会创建新会话"); + setVoiceState("idle", "本次对话已结束", "再次启动会创建一个新的会话。"); + setText("microphone", "已释放"); + setText("camera-status", "已释放"); + } catch (error) { + setText("error", error instanceof Error ? error.message : String(error)); + } finally { + unsubscribe?.(); + unsubscribe = undefined; + setSessionConnected(false); + startButton.disabled = false; + } +} + +async function toggleAudioInput(): Promise { + if (audioInputButton.disabled) return; + const next = !audioInputEnabled; + audioInputButton.disabled = true; + try { + await agent?.setAudioInputEnabled(next); + audioInputEnabled = next; + setSwitchState(audioInputButton, audioInputEnabled); + if (agent !== undefined) { + setVoiceState( + audioInputEnabled ? "ready" : "idle", + audioInputEnabled ? "我在听" : "语音输入已关闭", + audioInputEnabled ? "继续说,EVA 会自然接着聊。" : "打开麦克风,或使用下方文字输入。", + ); + } + setText("microphone", audioInputEnabled + ? (agent === undefined ? "启动时启用" : "已连接") + : (agent === undefined ? "启动时禁用" : "已释放")); + } catch (error) { + setText("error", error instanceof Error ? error.message : String(error)); + } finally { + audioInputButton.disabled = mediaControlsLocked; + } +} + +async function toggleTts(): Promise { + if (ttsButton.disabled) return; + const next = !ttsEnabled; + ttsButton.disabled = true; + try { + await agent?.setTtsEnabled(next); + ttsEnabled = next; + setSwitchState(ttsButton, ttsEnabled); + } catch (error) { + setText("error", error instanceof Error ? error.message : String(error)); + } finally { + ttsButton.disabled = mediaControlsLocked; + } +} + +async function toggleCamera(): Promise { + if (cameraButton.disabled) return; + const next = !cameraEnabled; + cameraButton.disabled = true; + try { + await agent?.setCameraCaptureEnabled(next); + cameraEnabled = next; + setSwitchState(cameraButton, cameraEnabled); + setText("camera-status", cameraEnabled + ? (agent === undefined ? "启动时启用" : "持续连接;说话时采一张图") + : (agent === undefined ? "启动时关闭" : "已释放")); + } catch (error) { + setText("error", error instanceof Error ? error.message : String(error)); + } finally { + cameraButton.disabled = mediaControlsLocked; + } +} + +async function submit(event: SubmitEvent): Promise { + event.preventDefault(); + const text = textInput.value.trim(); + const current = agent; + if (current === undefined || text.length === 0) return; + textInput.value = ""; + try { + await current.submitText(text, { metadata: { channel: "ts-electron-demo" } }); + } catch (error) { + setText("error", error instanceof Error ? error.message : String(error)); + } +} + +// SDK event → Demo 页面投影。Emotion / Command 配置是可选的,但 AgentEvent +// 仍表示完整公共事件目录,因此这里保留所有分支并用 never 做穷尽检查。 +function handleEvent(event: AgentEvent, sourceAgent: EvaVoiceDialogueAgent): void { + switch (event.type) { + case "speech.started": + setText("microphone", "检测到说话"); + setVoiceState("listening", "我在听", "继续说,停顿后 EVA 会自动理解并回应。"); + return; + case "image.captured": + setText( + "camera-status", + `${event.image.mimeType} · ${event.image.width}×${event.image.height} · ${event.image.sizeBytes} bytes · ${event.image.captureMs} ms`, + event.type, + ); + return; + case "speech.stopped": + setText("microphone", "识别中…"); + setVoiceState("processing", "正在理解", "EVA 正在整理刚才听到的内容。"); + return; + case "transcript.partial": + setText("transcript", event.text, event.type); + setVoiceState("listening", "我在听", event.text); + return; + case "transcript.final": + setText("transcript", event.text, event.type); + renderMessages(sourceAgent); + return; + case "interruption": + setText("interruption", `${event.reason} · ${event.turnId}`); + return; + case "reply.started": + setText("reply", "…", event.type); + setVoiceState("processing", "正在组织回应", "马上就好。"); + return; + case "reply.partial": + element("reply").textContent += event.text; + return; + case "reply.final": + setText("reply", event.text, event.type); + renderMessages(sourceAgent); + if (!ttsEnabled) { + setVoiceState( + audioInputEnabled ? "ready" : "idle", + audioInputEnabled ? "我在听" : "语音输入已关闭", + audioInputEnabled ? "继续说,EVA 会自然接着聊。" : "打开麦克风,或使用下方文字输入。", + ); + } + return; + case "playback.started": + setText("status", "播放回复"); + setVoiceState("speaking", "EVA 正在说话", "你可以随时开口打断。"); + return; + case "playback.stopped": + setText("status", "已接通"); + setVoiceState( + audioInputEnabled ? "ready" : "idle", + audioInputEnabled ? "我在听" : "语音输入已关闭", + audioInputEnabled ? "继续说,EVA 会自然接着聊。" : "打开麦克风,或使用下方文字输入。", + ); + return; + case "turn.latency": + setText("latency", JSON.stringify(event.latency, null, 2)); + return; + case "emotion.detected": + setText( + "emotion", + `${event.emotionCode} · ${event.source} · confidence ${event.confidence?.toFixed(3) ?? "—"} · ${event.latencyMs} ms · 「${event.textPreview}」`, + event.type, + ); + return; + case "command.called": + setText( + "command", + `调用中 · ${event.call.name} · ${event.call.argumentsJson}`, + event.type, + ); + return; + case "command.completed": + setText( + "command", + `已完成 · ${event.call.name} · ${event.result.message ?? "成功"}${formatCommandData(event.result.data)}`, + event.type, + ); + return; + case "command.failed": + setText( + "command", + `失败 · ${event.call.name} · ${event.result.message}${formatCommandData(event.result.data)}`, + event.type, + ); + return; + case "error": + if (event.error.source === "media" && event.error.role === "camera") { + if (event.error.operation === "start") { + cameraEnabled = false; + setSwitchState(cameraButton, false); + setText("camera-status", "不可用或未授权"); + } + } else { + setVoiceState("error", "遇到了一点问题", "请查看开发者诊断,或结束会话后重试。"); + } + setText("error", JSON.stringify(event.error, null, 2)); + return; + default: + event satisfies never; + return; + } +} + +function formatCommandData(data: unknown): string { + return data === undefined ? "" : ` · ${JSON.stringify(data)}`; +} + +// Demo-only 渲染与日志 helper。 +function renderMessages(source: EvaVoiceDialogueAgent): void { + const list = element("messages"); + const messages = source.getMessages(); + conversationEmpty.hidden = messages.length > 0; + list.replaceChildren(...messages.map((message) => { + const item = document.createElement("li"); + item.className = message.role; + const label = document.createElement("strong"); + label.textContent = message.role === "user" ? "你" : "EVA"; + const content = document.createElement("span"); + content.textContent = message.content; + item.append(label, content); + return item; + })); +} + +function setBusy(busy: boolean): void { + startButton.disabled = busy; + if (busy) submitButton.disabled = true; +} + +function setMediaControlsLocked(locked: boolean): void { + mediaControlsLocked = locked; + audioInputButton.disabled = locked; + ttsButton.disabled = locked; + cameraButton.disabled = locked; +} + +function setSessionConnected(connected: boolean): void { + startButton.hidden = connected; + stopButton.hidden = !connected; + stopButton.disabled = !connected; + if (connected) startCallTimer(); + else stopCallTimer(); +} + +function startCallTimer(): void { + stopCallTimer(); + callStartedAt = Date.now(); + callDuration.hidden = false; + renderCallDuration(); + callTimer = window.setInterval(renderCallDuration, 1_000); +} + +function stopCallTimer(): void { + if (callTimer !== undefined) window.clearInterval(callTimer); + callTimer = undefined; + callStartedAt = undefined; + callDuration.hidden = true; +} + +function renderCallDuration(): void { + if (callStartedAt === undefined) return; + const elapsedSeconds = Math.floor((Date.now() - callStartedAt) / 1_000); + const minutes = Math.floor(elapsedSeconds / 60).toString().padStart(2, "0"); + const seconds = (elapsedSeconds % 60).toString().padStart(2, "0"); + callDuration.textContent = `${minutes}:${seconds}`; +} + +function setSwitchState(button: HTMLButtonElement, checked: boolean): void { + button.setAttribute("aria-checked", String(checked)); +} + +function setVoiceState(state: VoiceStageState, title: string, hint: string): void { + voiceStage.dataset.state = state; + element("voice-state").textContent = title; + element("voice-hint").textContent = hint; +} + +function setText(id: string, value: string, logSource = id): void { + element(id).textContent = value; + appendLog(logSource, value); +} + +function appendLog(source: string, value: string): void { + const log = element("activity-log"); + const time = new Date().toLocaleTimeString("zh-CN", { hour12: false }); + log.value += `${log.value.length === 0 ? "" : "\n"}[${time}] ${source}: ${value.replaceAll("\n", " ")}`; + log.scrollTop = log.scrollHeight; +} + +function element(id: string): T { + const found = document.getElementById(id); + if (found === null) throw new Error(`Missing #${id}`); + return found as T; +} diff --git a/client-sdk/ts/electron-conversation-agent/src/sdk-usage.ts b/client-sdk/ts/electron-conversation-agent/src/sdk-usage.ts new file mode 100644 index 0000000..f1f53f0 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/src/sdk-usage.ts @@ -0,0 +1,160 @@ +import { + createEvaVoiceDialogueAgent, + type AgentEvent, + type CommandRegistration, + type EvaVoiceDialogueAgent, +} from "@autoark-ai/eva-client-sdk-ts"; +import type { MediaTransportsConfig } from "@autoark-ai/eva-client-sdk-ts/spi"; +import { + createBrowserAudioInputSource, + createBrowserAudioOutputSink, + createBrowserCameraSnapshotSource, + createPassthroughAecProcessor, +} from "@autoark-ai/eva-client-sdk-ts/browser"; + +export type { AgentEvent, EvaVoiceDialogueAgent }; + +type StartEvaAgentOptions = { + apiKey: string; + audioInputEnabled: boolean; + ttsEnabled: boolean; + cameraEnabled: boolean; + onEvent: (event: AgentEvent, source: EvaVoiceDialogueAgent) => void; +}; + +type StartedEvaAgent = { + agent: EvaVoiceDialogueAgent; + unsubscribe: () => void; +}; + +type PageTheme = "light" | "dark"; + +const demoCommandRegistrations: readonly CommandRegistration[] = [ + { + definition: { + name: "show_current_time", + description: "当用户询问当前时间时,查询当前页面所在设备的本地时间。", + }, + handler(_call, context) { + if (context.signal.aborted) { + return { ok: false, message: "Command cancelled" }; + } + const now = new Date(); + return { + ok: true, + message: `当前本地时间是 ${now.toLocaleTimeString()}`, + data: { + isoTime: now.toISOString(), + localTime: now.toLocaleString(), + timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }, + }; + }, + }, + { + definition: { + name: "set_page_theme", + description: "当用户要求切换页面外观时,将当前页面切换为指定的明暗主题。", + parameters: [{ + name: "theme", + description: "要应用的页面主题。", + type: "string", + required: true, + enum: ["light", "dark"], + example: "dark", + }], + }, + handler(call, context) { + if (context.signal.aborted) { + return { ok: false, message: "Command cancelled" }; + } + const theme = call.arguments.theme; + if (theme !== "light" && theme !== "dark") { + return { ok: false, message: "Unsupported page theme" }; + } + applyPageTheme(theme); + return { + ok: true, + message: `页面主题已切换为 ${theme}`, + data: { theme }, + }; + }, + }, +]; + +function applyPageTheme(theme: PageTheme): void { + document.documentElement.dataset.theme = theme; + document.documentElement.style.colorScheme = theme; +} + +/** + * SDK 接入主路径(Electron 渲染进程语音 demo)。 + * + * Electron 渲染进程运行在 Chromium 中,因此照常复用浏览器 Media SPI helper。 + * 页面弹窗、按钮状态、日志和消息渲染都留在 main.ts;这里连续展示: + * 1. 组合 Media SPI;2. 创建 Agent;3. 订阅事件;4. 配置初始状态并启动。 + */ +export async function startEvaAgent(options: StartEvaAgentOptions): Promise { + // 语音接入需要完整的 input / output / AEC;纯文本接入可以省略 transports 与 vad。 + const transports: MediaTransportsConfig = { + input: createBrowserAudioInputSource({ + maxBufferedChunks: 64, + echoCancellation: true, + noiseSuppression: true, + autoGainControl: true, + }), + output: createBrowserAudioOutputSink(), + aec: createPassthroughAecProcessor(), + // 默认 browser camera helper 是可替换的 CameraSnapshotSource;factory 不会自行申请权限。 + camera: createBrowserCameraSnapshotSource({ + video: { facingMode: { ideal: "user" } }, + mimeType: "image/png", + }), + }; + + // apiKey 与三个 model 是应用提供的接入配置;其余字段是本 demo 的选择。 + const agent = createEvaVoiceDialogueAgent({ + apiKey: options.apiKey, + asr: { model: "fun_asr", sampleRate: 48_000 }, + llm: { model: "doubao-seed-2-0-mini-nothink" }, + tts: { + model: "cosyvoice_tts", + voice: "longjielidou_v3", + sampleRate: 48_000, + }, + vad: { + sensitivity: 0.7, + silenceThresholdMs: 400, + }, + transports, + history: { maxTurns: 10 }, + camera: { captureTimeoutMs: 1500 }, + // 可选:省略 emotion(或设为 enabled: false)时不运行旁路分类,也不产生 emotion.detected。 + // custom labels 会替换默认业务标签;SDK 会自动补充 unknown。 + emotion: { enabled: true, labels: ["happy", "sad"] }, + // 可选:省略 commands(或提供空 registrations)时不向 LLM 暴露 command。 + commands: { + registrations: demoCommandRegistrations, + maxCallsPerTurn: 3, + }, + systemPrompt: [ + "你是一个简洁、自然的语音助手。", + "只有当前用户消息实际包含图片时,才可以描述当前看到的画面。", + "当前用户消息没有图片时,不得把历史中的视觉描述说成实时观察;", + "如需引用,只能明确说明那是之前看到的内容,并说明当前没有新的画面。", + ].join(""), + greeting: { mode: "static", text: "你好" }, + }); + + const unsubscribe = agent.onEvent((event) => options.onEvent(event, agent)); + try { + await agent.setAudioInputEnabled(options.audioInputEnabled); + await agent.setCameraCaptureEnabled(options.cameraEnabled); + await agent.setTtsEnabled(options.ttsEnabled); + await agent.start(); + return { agent, unsubscribe }; + } catch (error) { + unsubscribe(); + throw error; + } +} diff --git a/client-sdk/ts/electron-conversation-agent/src/styles.css b/client-sdk/ts/electron-conversation-agent/src/styles.css new file mode 100644 index 0000000..54162ee --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/src/styles.css @@ -0,0 +1,1141 @@ +:root { + --page-background: #f2f4f1; + --surface: #ffffff; + --surface-muted: #f7f8f6; + --border: #d9ded9; + --control-border: #c7cec8; + --text: #18201c; + --muted-text: #68736c; + --accent: #c7ff63; + --accent-strong: #7fb719; + --accent-text: #18210f; + --coral: #ff8066; + --stage: #171c1a; + --stage-muted: #a9b4ad; + --user-message: #e9f1ff; + --assistant-message: #eff8dd; + --diagnostic-background: #151a18; + --diagnostic-text: #d5e2d9; + --error: #b42318; + --shadow: #14231a10; + --dialog-shadow: #14221b40; + --backdrop: #14221b80; + font-family: Inter, "SF Pro Display", "PingFang SC", "Microsoft YaHei", ui-sans-serif, system-ui, sans-serif; + color: var(--text); + background: var(--page-background); +} + +:root[data-theme="dark"] { + --page-background: #111513; + --surface: #1d2320; + --surface-muted: #252c28; + --border: #39423d; + --control-border: #4b5750; + --text: #f0f4f1; + --muted-text: #aab5ae; + --accent: #c7ff63; + --accent-strong: #a5dc41; + --accent-text: #18210f; + --stage: #080b0a; + --stage-muted: #aeb9b2; + --user-message: #23354f; + --assistant-message: #303d22; + --diagnostic-background: #090c0b; + --diagnostic-text: #d3ead9; + --error: #ff9b92; + --shadow: #0000002e; + --dialog-shadow: #00000066; + --backdrop: #00000099; +} + +* { + box-sizing: border-box; +} + +[hidden] { + display: none !important; +} + +body { + margin: 0; + min-height: 100vh; + background: var(--page-background); +} + +button, +input, +textarea { + font: inherit; +} + +button { + cursor: pointer; +} + +button:focus-visible, +input:focus-visible, +summary:focus-visible { + outline: 3px solid color-mix(in srgb, var(--accent-strong) 45%, transparent); + outline-offset: 3px; +} + +button:disabled { + cursor: not-allowed; + opacity: .42; +} + +main { + width: min(1080px, calc(100% - 40px)); + margin: 0 auto; + padding: 24px 0 48px; +} + +h1, +h2, +p { + margin-top: 0; +} + +.app-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + min-height: 64px; + margin-bottom: 20px; +} + +.brand { + display: flex; + align-items: center; + gap: 12px; +} + +.brand-mark { + display: grid; + width: 42px; + height: 42px; + place-items: center; + border-radius: 7px; + background: var(--text); + color: var(--accent); + font-size: 1.2rem; + font-weight: 900; +} + +.eyebrow, +.section-kicker { + margin-bottom: 2px; + color: var(--muted-text); + font-size: .68rem; + font-weight: 800; + letter-spacing: .08em; + text-transform: uppercase; +} + +.app-header h1 { + margin: 0; + font-size: 1.25rem; + line-height: 1.15; + letter-spacing: 0; +} + +.sdk-label { + margin: 0; + color: var(--muted-text); + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: .75rem; +} + +.voice-stage { + position: relative; + display: grid; + grid-template-columns: minmax(220px, .9fr) minmax(300px, 1.2fr) minmax(180px, .7fr); + min-height: 360px; + align-items: center; + gap: 28px; + overflow: hidden; + padding: 44px; + border-radius: 8px; + background: var(--stage); + color: #f7faf8; + box-shadow: 0 24px 60px #111b161f; +} + +.voice-stage::before { + position: absolute; + inset: 0; + background-image: + linear-gradient(#ffffff08 1px, transparent 1px), + linear-gradient(90deg, #ffffff08 1px, transparent 1px); + background-size: 40px 40px; + content: ""; + mask-image: linear-gradient(90deg, transparent, #000 50%, transparent); + pointer-events: none; +} + +.voice-copy, +.voice-visual, +.session-actions { + position: relative; + z-index: 1; +} + +.stage-kicker { + display: flex; + align-items: center; + gap: 9px; + margin-bottom: 20px; + color: var(--stage-muted); + font-size: .8rem; + font-weight: 700; +} + +.call-duration { + margin-left: 5px; + padding-left: 12px; + border-left: 1px solid #ffffff26; + color: #f7faf8; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-variant-numeric: tabular-nums; +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: #67716b; + box-shadow: 0 0 0 4px #67716b1f; +} + +.voice-stage h2 { + max-width: 340px; + margin-bottom: 14px; + font-size: 2.4rem; + line-height: 1.08; + letter-spacing: 0; +} + +#voice-hint { + max-width: 330px; + margin-bottom: 0; + color: var(--stage-muted); + font-size: .95rem; + line-height: 1.65; +} + +.voice-visual { + display: grid; + min-width: 0; + min-height: 220px; + place-items: center; +} + +.voice-visual::before, +.voice-visual::after { + position: absolute; + width: min(100%, 330px); + height: min(100%, 220px); + border: 1px solid #ffffff12; + border-radius: 50%; + content: ""; + transform-origin: center; +} + +.voice-visual::after { + width: min(80%, 260px); + height: min(78%, 172px); + border-color: #ffffff0c; +} + +.waveform { + position: relative; + z-index: 1; + display: flex; + width: min(100%, 290px); + height: 148px; + align-items: center; + justify-content: center; + gap: 5px; +} + +.waveform span { + width: 5px; + height: 12px; + border-radius: 3px; + background: var(--accent); + box-shadow: 0 0 18px #c7ff6330; + transform-origin: center; + animation: idle-wave 2.6s ease-in-out infinite alternate; +} + +.waveform span:nth-child(3n) { height: 24px; } +.waveform span:nth-child(4n) { height: 38px; } +.waveform span:nth-child(5n) { height: 58px; } +.waveform span:nth-child(7n) { height: 82px; } +.waveform span:nth-child(11n) { height: 108px; } + +.session-actions { + display: grid; + justify-items: stretch; + gap: 10px; +} + +.primary-action, +.stop-action { + display: inline-flex; + min-height: 52px; + align-items: center; + justify-content: center; + gap: 10px; + border-radius: 6px; + padding: 12px 18px; + font-weight: 800; +} + +.primary-action { + border: 1px solid var(--accent); + background: var(--accent); + color: var(--accent-text); +} + +.primary-action:hover:not(:disabled) { + background: #d4ff84; +} + +.stop-action { + border: 1px solid var(--coral); + background: var(--coral); + color: #2b100b; +} + +.stop-action:hover:not(:disabled) { + background: #ff9a84; +} + +.mic-icon { + position: relative; + display: inline-block; + width: 13px; + height: 18px; + border: 2px solid currentColor; + border-radius: 8px; +} + +.mic-icon::before { + position: absolute; + right: -5px; + bottom: -6px; + left: -5px; + height: 8px; + border-right: 2px solid currentColor; + border-bottom: 2px solid currentColor; + border-left: 2px solid currentColor; + border-radius: 0 0 9px 9px; + content: ""; +} + +.mic-icon::after { + position: absolute; + bottom: -10px; + left: 4px; + width: 2px; + height: 5px; + background: currentColor; + content: ""; +} + +.stop-icon { + width: 18px; + height: 10px; + border-right: 4px solid currentColor; + border-bottom: 4px solid currentColor; + border-left: 4px solid currentColor; + border-radius: 0 0 12px 12px; + transform: rotate(180deg); +} + +.voice-stage[data-state="starting"] .status-dot, +.voice-stage[data-state="processing"] .status-dot { + background: #ffd76a; + box-shadow: 0 0 0 4px #ffd76a24; +} + +.voice-stage[data-state="ready"] .status-dot, +.voice-stage[data-state="listening"] .status-dot, +.voice-stage[data-state="speaking"] .status-dot { + background: var(--accent); + box-shadow: 0 0 0 4px #c7ff6324; +} + +.voice-stage[data-state="error"] .status-dot { + background: var(--coral); + box-shadow: 0 0 0 4px #ff806624; +} + +.voice-stage[data-state="starting"] .waveform span, +.voice-stage[data-state="processing"] .waveform span { + animation: pulse-wave 1.2s ease-in-out infinite alternate; +} + +.voice-stage[data-state="ready"] .waveform span { + animation: ready-wave 1.7s ease-in-out infinite alternate; +} + +.voice-stage[data-state="listening"] .waveform span { + animation: active-wave .68s ease-in-out infinite alternate; +} + +.voice-stage[data-state="speaking"] .waveform span { + animation: active-wave .82s cubic-bezier(.45, 0, .55, 1) infinite alternate; +} + +.voice-stage[data-state="speaking"] .waveform span { + background: var(--coral); + box-shadow: 0 0 18px #ff806638; +} + +.voice-stage[data-state="idle"] .voice-visual::after, +.voice-stage[data-state="ready"] .voice-visual::after { + animation: ambient-ring 3.4s ease-in-out infinite; +} + +.voice-stage[data-state="listening"] .voice-visual::before, +.voice-stage[data-state="speaking"] .voice-visual::before { + animation: active-ring 1.6s ease-out infinite; +} + +.waveform span:nth-child(2n) { animation-delay: -.15s !important; } +.waveform span:nth-child(3n) { animation-delay: -.3s !important; } +.waveform span:nth-child(5n) { animation-delay: -.45s !important; } +.waveform span:nth-child(7n) { animation-delay: -.6s !important; } + +@keyframes active-wave { + from { transform: scaleY(.25); } + to { transform: scaleY(1); } +} + +@keyframes idle-wave { + from { transform: scaleY(.62); opacity: .58; } + to { transform: scaleY(.88); opacity: .88; } +} + +@keyframes ready-wave { + from { transform: scaleY(.42); opacity: .72; } + to { transform: scaleY(1); opacity: 1; } +} + +@keyframes pulse-wave { + from { transform: scaleY(.5); opacity: .55; } + to { transform: scaleY(1); opacity: 1; } +} + +@keyframes ambient-ring { + 0%, 100% { transform: scale(.96); opacity: .45; } + 50% { transform: scale(1.03); opacity: 1; } +} + +@keyframes active-ring { + 0% { transform: scale(.86); opacity: .8; } + 75%, 100% { transform: scale(1.08); opacity: 0; } +} + +.device-bar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + padding: 18px 2px; + border-bottom: 1px solid var(--border); +} + +.device-title { + margin-bottom: 2px; + font-size: .9rem; + font-weight: 800; +} + +.device-description { + margin-bottom: 0; + color: var(--muted-text); + font-size: .75rem; +} + +.device-controls { + display: flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; +} + +.switch-control { + display: inline-grid; + grid-template-columns: 22px auto 30px; + min-height: 42px; + align-items: center; + gap: 8px; + border: 1px solid var(--control-border); + border-radius: 6px; + padding: 8px 10px; + background: var(--surface); + color: var(--text); + font-size: .78rem; + font-weight: 700; +} + +.switch-control:hover:not(:disabled) { + border-color: var(--accent-strong); +} + +.control-icon { + justify-self: center; + transform: scale(.68); +} + +.speaker-icon { + position: relative; + display: inline-block; + width: 10px; + height: 12px; + background: currentColor; + clip-path: polygon(0 32%, 36% 32%, 100% 0, 100% 100%, 36% 68%, 0 68%); +} + +.speaker-icon::after { + position: absolute; + top: 1px; + left: 10px; + width: 7px; + height: 10px; + border-right: 2px solid currentColor; + border-radius: 50%; + content: ""; +} + +.camera-icon { + position: relative; + display: inline-block; + width: 18px; + height: 13px; + border: 2px solid currentColor; + border-radius: 3px; +} + +.camera-icon::after { + position: absolute; + top: 2px; + right: -7px; + border-width: 3px 5px 3px 0; + border-style: solid; + border-color: transparent currentColor transparent transparent; + content: ""; + transform: rotate(180deg); +} + +.switch-indicator { + position: relative; + width: 30px; + height: 18px; + border-radius: 9px; + background: #c4cbc6; + transition: background .2s ease; +} + +.switch-indicator::after { + position: absolute; + top: 3px; + left: 3px; + width: 12px; + height: 12px; + border-radius: 50%; + background: #fff; + box-shadow: 0 1px 3px #00000036; + content: ""; + transition: transform .2s ease; +} + +.switch-control[aria-checked="true"] .switch-indicator { + background: var(--accent-strong); +} + +.switch-control[aria-checked="true"] .switch-indicator::after { + transform: translateX(12px); +} + +.conversation { + padding: 34px 0 0; +} + +.section-heading { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-bottom: 16px; +} + +.section-heading h2 { + margin: 0; + font-size: 1rem; +} + +.conversation-heading h2 { + font-size: 1.6rem; +} + +.privacy-note { + color: var(--muted-text); + font-size: .75rem; +} + +.messages { + display: grid; + max-height: 420px; + gap: 16px; + overflow-y: auto; + padding: 0; + list-style: none; +} + +.messages:not(:empty) { + margin: 26px 0; +} + +.messages li { + display: flex; + width: max-content; + max-width: 76%; + gap: 12px; + align-items: start; +} + +.messages li strong { + display: grid; + width: 42px; + height: 42px; + place-items: center; + border-radius: 6px; + background: var(--text); + color: var(--surface); + font-size: .72rem; + flex: 0 0 42px; +} + +.messages li span { + min-width: 0; + max-width: min(720px, calc(100vw - 130px)); + overflow-wrap: anywhere; + padding: 12px 14px; + border-radius: 6px; + line-height: 1.6; +} + +.messages .user { + justify-self: end; +} + +.messages .user strong { + order: 2; +} + +.messages .user span { + background: var(--user-message); +} + +.messages .assistant span { + background: var(--assistant-message); +} + +.messages .assistant strong { + background: var(--accent-strong); + color: #fff; +} + +.conversation-empty { + display: grid; + min-height: 160px; + place-items: center; + align-content: center; + gap: 16px; + border-top: 1px solid var(--border); + border-bottom: 1px solid var(--border); + color: var(--muted-text); + text-align: center; +} + +.conversation-empty[hidden] { + display: none; +} + +.conversation-empty p { + margin: 0; + font-size: .84rem; +} + +.empty-wave { + width: 72px; + height: 28px; + background: + linear-gradient(90deg, + transparent 0 4px, var(--control-border) 4px 7px, + transparent 7px 13px, var(--control-border) 13px 16px, + transparent 16px 22px, var(--control-border) 22px 25px, + transparent 25px 31px, var(--control-border) 31px 34px, + transparent 34px 40px, var(--control-border) 40px 43px, + transparent 43px 49px, var(--control-border) 49px 52px, + transparent 52px 58px, var(--control-border) 58px 61px, + transparent 61px); + clip-path: polygon(0 42%, 8% 42%, 8% 30%, 16% 30%, 16% 5%, 24% 5%, 24% 26%, 32% 26%, 32% 40%, 40% 40%, 40% 16%, 48% 16%, 48% 0, 56% 0, 56% 20%, 64% 20%, 64% 36%, 72% 36%, 72% 18%, 80% 18%, 80% 34%, 88% 34%, 88% 42%, 100% 42%, 100% 58%, 88% 58%, 88% 66%, 80% 66%, 80% 82%, 72% 82%, 72% 64%, 64% 64%, 64% 80%, 56% 80%, 56% 100%, 48% 100%, 48% 84%, 40% 84%, 40% 60%, 32% 60%, 32% 74%, 24% 74%, 24% 95%, 16% 95%, 16% 70%, 8% 70%, 8% 58%, 0 58%); +} + +.live-turn { + display: grid; + grid-template-columns: 1fr 1fr; + border-bottom: 1px solid var(--border); +} + +.live-turn article { + min-height: 132px; + padding: 24px 0; +} + +.live-turn article + article { + border-left: 1px solid var(--border); + padding-left: 28px; +} + +.live-turn article:first-child { + padding-right: 28px; +} + +.live-label { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 12px; + color: var(--muted-text); + font-size: .7rem; + font-weight: 800; + text-transform: uppercase; +} + +.live-dot { + width: 7px; + height: 7px; + border-radius: 50%; +} + +.user-dot { background: #6b98d7; } +.eva-dot { background: var(--accent-strong); } + +#transcript, +#reply { + margin-bottom: 0; + line-height: 1.6; +} + +.text-composer { + display: grid; + grid-template-columns: 1fr 44px; + gap: 10px; + padding-top: 20px; +} + +.text-composer input { + min-width: 0; + height: 46px; + border: 1px solid var(--control-border); + border-radius: 6px; + padding: 0 14px; + background: var(--surface); + color: var(--text); +} + +.text-composer button { + display: grid; + width: 44px; + height: 44px; + align-self: center; + place-items: center; + border: 0; + border-radius: 50%; + background: var(--text); + color: var(--surface); +} + +.send-icon { + position: relative; + display: block; + width: 22px; + height: 16px; +} + +.send-icon::before, +.send-icon::after { + position: absolute; + content: ""; +} + +.send-icon::before { + top: 7px; + left: 1px; + width: 19px; + height: 2px; + border-radius: 999px; + background: currentColor; +} + +.send-icon::after { + top: 3px; + right: 1px; + width: 8px; + height: 8px; + border-top: 2px solid currentColor; + border-right: 2px solid currentColor; + transform: rotate(45deg); +} + +.diagnostics { + margin-top: 34px; + border-top: 1px solid var(--border); +} + +.diagnostics summary { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 58px; + color: var(--muted-text); + cursor: pointer; + font-size: .82rem; + font-weight: 800; + list-style: none; +} + +.diagnostics summary::-webkit-details-marker { + display: none; +} + +.diagnostics summary::after { + width: 8px; + height: 8px; + margin-left: auto; + border-right: 2px solid currentColor; + border-bottom: 2px solid currentColor; + content: ""; + transform: rotate(45deg); + transition: transform .2s ease; +} + +.diagnostics[open] summary::after { + transform: rotate(225deg); +} + +.summary-hint { + margin-right: 18px; + font-size: .7rem; + font-weight: 500; +} + +.diagnostic-content { + display: grid; + grid-template-columns: 1.2fr .8fr; + gap: 16px; + padding-bottom: 16px; +} + +.diagnostic-panel { + min-width: 0; + padding: 20px; + border: 1px solid var(--border); + border-radius: 6px; + background: var(--surface); + box-shadow: 0 10px 30px var(--shadow); +} + +.diagnostic-panel h2 { + font-size: .9rem; +} + +.secondary-button { + border: 1px solid var(--control-border); + border-radius: 5px; + padding: 6px 9px; + background: var(--surface); + color: var(--text); + font-size: .72rem; +} + +#activity-log { + width: 100%; + resize: vertical; + border: 0; + border-radius: 5px; + padding: 14px; + background: var(--diagnostic-background); + color: var(--diagnostic-text); + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: .75rem; + line-height: 1.55; +} + +dl { + margin: 0; +} + +dl div { + display: grid; + grid-template-columns: 82px 1fr; + gap: 10px; + margin: 9px 0; + font-size: .78rem; +} + +dt { + color: var(--muted-text); + font-weight: 700; +} + +dd { + margin: 0; + overflow-wrap: anywhere; +} + +pre { + overflow: auto; + border-radius: 5px; + padding: 14px; + background: var(--diagnostic-background); + color: var(--diagnostic-text); + font-size: .72rem; +} + +dialog { + width: min(460px, calc(100% - 32px)); + border: 1px solid var(--border); + border-radius: 8px; + padding: 0; + color: var(--text); + background: var(--surface); + box-shadow: 0 24px 70px var(--dialog-shadow); +} + +dialog::backdrop { + background: var(--backdrop); + backdrop-filter: blur(3px); +} + +.api-key-form { + display: grid; + gap: 12px; + padding: 24px; +} + +.api-key-form h2, +.api-key-form p { + margin: 0; +} + +.api-key-form label { + font-weight: 700; +} + +#api-key-input { + width: 100%; + min-height: 42px; + border: 1px solid var(--control-border); + border-radius: 6px; + padding: 8px 10px; + background: var(--surface-muted); + color: var(--text); +} + +.field-error { + min-height: 1.25em; + color: var(--error); + font-size: .875rem; +} + +.dialog-actions { + display: flex; + justify-content: flex-end; + gap: 10px; +} + +.dialog-actions button { + min-height: 40px; + border: 1px solid var(--control-border); + border-radius: 6px; + padding: 8px 12px; + background: var(--text); + color: var(--surface); +} + +.dialog-actions .secondary-button { + background: var(--surface); + color: var(--text); +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0 0 0 0); + clip-path: inset(50%); + white-space: nowrap; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; + } +} + +@media (max-width: 820px) { + .voice-stage { + grid-template-columns: 1fr 1fr; + min-height: 420px; + padding: 34px; + } + + .voice-copy { + grid-column: 1; + } + + .voice-visual { + grid-column: 2; + grid-row: 1 / span 2; + } + + .session-actions { + grid-column: 1; + } + + .device-bar { + align-items: flex-start; + } + + .diagnostic-content { + grid-template-columns: 1fr; + } +} + +@media (max-width: 620px) { + main { + width: min(100% - 24px, 1080px); + padding-top: 14px; + } + + .app-header { + min-height: 54px; + margin-bottom: 12px; + } + + .sdk-label { + display: none; + } + + .voice-stage { + grid-template-columns: 1fr; + min-height: 560px; + gap: 12px; + padding: 28px 22px 22px; + text-align: center; + } + + .voice-copy, + .voice-visual, + .session-actions { + grid-column: 1; + } + + .voice-copy { + grid-row: 1; + } + + .voice-visual { + grid-row: 2; + min-height: 190px; + } + + .session-actions { + grid-row: 3; + } + + .stage-kicker { + justify-content: center; + } + + .voice-stage h2, + #voice-hint { + margin-right: auto; + margin-left: auto; + } + + .voice-stage h2 { + font-size: 2rem; + } + + .device-bar { + display: block; + padding: 16px 0; + } + + .device-bar > div:first-child { + margin-bottom: 12px; + } + + .device-controls { + display: grid; + grid-template-columns: 1fr; + } + + .switch-control { + grid-template-columns: 24px 1fr 30px; + justify-items: start; + } + + .conversation { + padding-top: 28px; + } + + .privacy-note { + display: none; + } + + .messages li { + max-width: 92%; + } + + .live-turn { + grid-template-columns: 1fr; + } + + .live-turn article { + min-height: 112px; + padding: 20px 0; + } + + .live-turn article + article { + border-top: 1px solid var(--border); + border-left: 0; + padding-left: 0; + } + + .live-turn article:first-child { + padding-right: 0; + } + + .summary-hint { + display: none; + } + + .diagnostic-panel { + padding: 14px; + } +} diff --git a/client-sdk/ts/electron-conversation-agent/tsconfig.electron.json b/client-sdk/ts/electron-conversation-agent/tsconfig.electron.json new file mode 100644 index 0000000..34db03a --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/tsconfig.electron.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "CommonJS", + "moduleResolution": "Node", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "dist-electron", + "rootDir": "electron", + "sourceMap": true, + "types": ["node"] + }, + "include": ["electron"] +} diff --git a/client-sdk/ts/electron-conversation-agent/tsconfig.json b/client-sdk/ts/electron-conversation-agent/tsconfig.json new file mode 100644 index 0000000..f8978b8 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "noEmit": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["vite/client"] + }, + "include": ["src"] +} diff --git a/client-sdk/ts/electron-conversation-agent/vite.config.ts b/client-sdk/ts/electron-conversation-agent/vite.config.ts new file mode 100644 index 0000000..ed9aa24 --- /dev/null +++ b/client-sdk/ts/electron-conversation-agent/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; + +export default defineConfig({ + // 相对 base 让 vite build 产物使用相对资产路径,Electron 主进程可以直接 + // 通过 loadFile 加载 dist/index.html,而不依赖任何服务器根路径。 + base: "./", +}); diff --git a/examples.json b/examples.json index 4dd8fd2..c17b95a 100644 --- a/examples.json +++ b/examples.json @@ -13,6 +13,19 @@ "package": "@autoark-ai/eva-client-sdk-ts" }, "status": "release" + }, + { + "id": "client-sdk-ts-electron-conversation-agent", + "title": "EVA Client SDK · TypeScript Electron Conversation Agent", + "sdkFamily": "client-sdk", + "language": "ts", + "platform": "electron", + "path": "client-sdk/ts/electron-conversation-agent", + "sdk": { + "ecosystem": "npm", + "package": "@autoark-ai/eva-client-sdk-ts" + }, + "status": "dev" } ] }