From 2ac67098b0d52d7389ee2436b6867b59f4266661 Mon Sep 17 00:00:00 2001 From: Guilimao_Official <1137056144@qq.com> Date: Fri, 14 Aug 2026 17:08:22 +0800 Subject: [PATCH 1/3] feat(providers): replace settings-based credentials with pi-ai registry and SecretStorage - Introduce llm/providerService on top of pi-ai's multi-protocol catalog with /models discovery and reasoning-effort metadata - Store API keys in VS Code SecretStorage via new 'Manage Model Providers' command; keys never touch settings, .mtm, caches, or logs - Deprecate mutsumi.providers / mutsumi.models (migration-only); add 'Migrate Legacy Provider Credentials' and secure migration prompt - Add mutsumi.customProviders for custom OpenAI-compatible routes (api/auth/models) - Rename built-in provider kimi-for-coding -> kimi-coding - Drop direct openai SDK dependency; switch runner/tools to provider-neutral pi-ai types; persist pi-ai replay state in message metadata - Add vitest unit tests for provider service, credentials, migration, and replay --- README.md | 18 +- README_zh.md | 18 +- docs/AGENT_TYPES_DESIGN.md | 8 +- docs/AGENT_TYPES_DESIGN_CN.md | 8 +- docs/HTTP_SERVER_SECURITY_DESIGN_CN.md | 2 +- docs/multi-provider-refactor.md | 4 +- docs/mutsumi_config_structure.json | 78 +- l10n/bundle.l10n.json | 49 +- l10n/bundle.l10n.zh-cn.json | 49 +- package-lock.json | 12902 ++++++++++------ package.json | 135 +- package.nls.json | 11 +- package.nls.zh-cn.json | 11 +- src/adapters/interfaces.ts | 4 - src/agent/agentRunner.ts | 11 +- src/agent/fileOps.ts | 2 +- src/agent/llmClient.ts | 328 +- src/agent/llmStream.ts | 85 +- src/agent/titleGenerator.ts | 32 +- src/agent/toolExecutor.ts | 5 + src/agent/types.ts | 8 +- src/config/resolver.ts | 2 +- src/config/types.ts | 8 +- src/controller.ts | 32 +- src/extension.ts | 15 + src/httpServer/chat.ts | 18 +- src/llm/context.ts | 76 + src/llm/credentialStore.ts | 87 + src/llm/migration.ts | 165 + src/llm/modelStore.ts | 26 + src/llm/providerService.ts | 431 + src/llm/replay.ts | 169 + src/llm/types.ts | 61 + src/mcp/tool.ts | 4 +- src/notebook/commands/compressConversation.ts | 16 +- src/notebook/commands/index.ts | 1 + src/notebook/commands/manageProviders.ts | 218 + src/notebook/commands/selectModel.ts | 49 +- src/notebook/toolbar.ts | 2 + src/tools.d/interface.ts | 13 +- src/tools.d/toolManager.ts | 13 +- src/types.ts | 32 +- src/utils.ts | 101 +- tests/credentialStore.test.ts | 47 + tests/llmClient.test.ts | 55 + tests/migration.test.ts | 113 + tests/providerService.test.ts | 161 + tests/replayAndContext.test.ts | 68 + tests/tsconfig.json | 10 + tsconfig.json | 2 + vitest.config.ts | 9 + 51 files changed, 10271 insertions(+), 5501 deletions(-) create mode 100644 src/llm/context.ts create mode 100644 src/llm/credentialStore.ts create mode 100644 src/llm/migration.ts create mode 100644 src/llm/modelStore.ts create mode 100644 src/llm/providerService.ts create mode 100644 src/llm/replay.ts create mode 100644 src/llm/types.ts create mode 100644 src/notebook/commands/manageProviders.ts create mode 100644 tests/credentialStore.test.ts create mode 100644 tests/llmClient.test.ts create mode 100644 tests/migration.test.ts create mode 100644 tests/providerService.test.ts create mode 100644 tests/replayAndContext.test.ts create mode 100644 tests/tsconfig.json create mode 100644 vitest.config.ts diff --git a/README.md b/README.md index a005a1f..baea662 100644 --- a/README.md +++ b/README.md @@ -275,21 +275,15 @@ code --install-extension mutsumi-[version].vsix ### Configuration -Mutsumi defaults to the `kimi-for-coding` model. To get started, simply add your API key in VS Code: settings. +Mutsumi defaults to the `kimi-for-coding` model on the built-in `kimi-coding` provider. -Open your `settings.json` and add: +1. Open the Command Palette and run **Mutsumi: Manage Model Providers**. +2. Select Kimi Coding (or another built-in provider) and enter its API key. +3. Run **Mutsumi: Select Model** to choose from providers that are authenticated by VS Code SecretStorage or a supported environment credential. -```json -"mutsumi.providers": [ - { - "name": "kimi-for-coding", - "baseurl": "https://api.kimi.com/coding/v1", - "api_key": "sk-kimi-XXXXXXXXXXXXXXXXXXXXXX" - } -] -``` +Keys are entered through a password input and stored in VS Code SecretStorage. They are never written to settings, `.mtm` files, model caches, or logs. The provider manager also supports non-secret custom OpenAI-compatible routes and `/models` discovery. -If you want to use a different model or provider, configure `mutsumi.providers` and `mutsumi.models` accordingly. See the setting descriptions in VS Code: for examples. +Existing `mutsumi.providers` / `mutsumi.models` configurations are migration-only. On upgrade, accept the secure migration prompt or run **Mutsumi: Migrate Legacy Provider Credentials** manually. Rotate any key previously committed to version control. > **Note:** This Agent framework is specifically designed and optimized around the Kimi base model family. Using `kimi-for-coding` is highly recommended. diff --git a/README_zh.md b/README_zh.md index 62f27f3..5d1a087 100644 --- a/README_zh.md +++ b/README_zh.md @@ -275,21 +275,15 @@ code --install-extension mutsumi-【版本号】.vsix ### 配置 -Mutsumi 默认使用 `kimi-for-coding` 模型。你只需在 VS Code 设置中填入 API Key 即可开始使用。 +Mutsumi 默认使用内置 `kimi-coding` 提供商的 `kimi-for-coding` 模型。 -打开 `settings.json`,添加: +1. 打开命令面板,运行 **Mutsumi: 管理模型提供商**。 +2. 选择 Kimi Coding(或其他内置提供商)并输入 API Key。 +3. 运行 **Mutsumi: 选择模型**,从已由 VS Code SecretStorage 或受支持环境凭据完成鉴权的提供商中选择模型。 -```json -"mutsumi.providers": [ - { - "name": "kimi-for-coding", - "baseurl": "https://api.kimi.com/coding/v1", - "api_key": "sk-kimi-XXXXXXXXXXXXXXXXXXXXXX" - } -] -``` +密钥通过密码输入框录入并存入 VS Code SecretStorage,绝不会写入设置、`.mtm` 文件、模型缓存或日志。提供商管理器还支持不含秘密的自定义 OpenAI-compatible 路由及 `/models` 自动发现。 -如需使用其他模型或服务商,可相应配置 `mutsumi.providers` 和 `mutsumi.models`,具体示例请参见 VS Code 设置中的说明。 +旧版 `mutsumi.providers` / `mutsumi.models` 配置仅用于迁移。升级时可接受安全迁移提示,或手动运行 **Mutsumi: 迁移旧版提供商凭据**。若密钥曾提交到版本控制,请在服务商侧轮换。 > **注意:** 本 Agent 框架针对 Kimi 基模家族调性优化设计,强烈建议使用 `kimi-for-coding`。 diff --git a/docs/AGENT_TYPES_DESIGN.md b/docs/AGENT_TYPES_DESIGN.md index aaf9429..622c6ec 100644 --- a/docs/AGENT_TYPES_DESIGN.md +++ b/docs/AGENT_TYPES_DESIGN.md @@ -187,7 +187,7 @@ If the file does not exist, Mutsumi loads built-in defaults from `src/config/typ "agentTypes": { "chat": { "toolSets": ["read"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/chat.md"], "defaultSkills": [], "allowedChildTypes": [], @@ -195,7 +195,7 @@ If the file does not exist, Mutsumi loads built-in defaults from `src/config/typ }, "implementer": { "toolSets": ["read", "deliver", "dispatch"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/implementer.md"], "defaultSkills": [], "allowedChildTypes": ["implementer", "reviewer"], @@ -203,7 +203,7 @@ If the file does not exist, Mutsumi loads built-in defaults from `src/config/typ }, "orchestrator": { "toolSets": ["read", "deliver", "dispatch"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/orchestrator.md"], "defaultSkills": [], "allowedChildTypes": ["implementer", "reviewer"], @@ -211,7 +211,7 @@ If the file does not exist, Mutsumi loads built-in defaults from `src/config/typ }, "reviewer": { "toolSets": ["read"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/reviewer.md"], "defaultSkills": [], "allowedChildTypes": [], diff --git a/docs/AGENT_TYPES_DESIGN_CN.md b/docs/AGENT_TYPES_DESIGN_CN.md index 60c455c..6abc178 100644 --- a/docs/AGENT_TYPES_DESIGN_CN.md +++ b/docs/AGENT_TYPES_DESIGN_CN.md @@ -187,7 +187,7 @@ Agent Type 不实现通用继承。 "agentTypes": { "chat": { "toolSets": ["read"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/chat.md"], "defaultSkills": [], "allowedChildTypes": [], @@ -195,7 +195,7 @@ Agent Type 不实现通用继承。 }, "implementer": { "toolSets": ["read", "deliver", "dispatch"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/implementer.md"], "defaultSkills": [], "allowedChildTypes": ["implementer", "reviewer"], @@ -203,7 +203,7 @@ Agent Type 不实现通用继承。 }, "orchestrator": { "toolSets": ["read", "deliver", "dispatch"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/orchestrator.md"], "defaultSkills": [], "allowedChildTypes": ["implementer", "reviewer"], @@ -211,7 +211,7 @@ Agent Type 不实现通用继承。 }, "reviewer": { "toolSets": ["read"], - "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-for-coding" }, + "defaultModel": { "model": "kimi-for-coding", "provider": "kimi-coding" }, "defaultRules": ["default/reviewer.md"], "defaultSkills": [], "allowedChildTypes": [], diff --git a/docs/HTTP_SERVER_SECURITY_DESIGN_CN.md b/docs/HTTP_SERVER_SECURITY_DESIGN_CN.md index 52d7d62..df72f53 100644 --- a/docs/HTTP_SERVER_SECURITY_DESIGN_CN.md +++ b/docs/HTTP_SERVER_SECURITY_DESIGN_CN.md @@ -20,7 +20,7 @@ HTTP Server 默认关闭;用户显式开启后,所有端点必须携带正 | 决策点 | 结论 | |---|---| | 认证头 | 标准 `Authorization: Bearer `(scheme 匹配按 RFC 7235 大小写不敏感) | -| 密码存储 | 明文存于 VS Code 设置(与现有 `mutsumi.providers[].api_key` 明文策略一致),设置描述中注明 | +| 密码存储 | HTTP Server 密码仍按本设计存于 VS Code 设置;LLM API Key 已独立迁移到 VS Code SecretStorage,不再以此作为类比 | | 密码比较 | 常量时间比较(`crypto.timingSafeEqual` 或等效手段),避免时序侧信道 | | 空密码行为 | `enabled=true` 但密码为空 → **拒绝启动**,弹警告通知,提供"打开设置"与"生成随机密码"入口 | | 浏览器/CSRF 防护 | 不实现。Bearer 头本身即非简单请求头,天然阻断浏览器预检外请求;无浏览器使用场景 | diff --git a/docs/multi-provider-refactor.md b/docs/multi-provider-refactor.md index fab3893..e92ddf3 100644 --- a/docs/multi-provider-refactor.md +++ b/docs/multi-provider-refactor.md @@ -1,6 +1,8 @@ # Multi-Provider Configuration -This document describes the implemented multi-provider configuration design in Mutsumi. It is not a future plan; it reflects the current behavior after the strict breaking refactor. +> Superseded by the pi-ai provider registry and SecretStorage integration. `mutsumi.providers` and `mutsumi.models` below describe the one-release migration input only; do not add new API keys to settings. Use **Mutsumi: Manage Model Providers** and `mutsumi.customProviders` instead. + +This document is retained as a record of the legacy settings-based multi-provider design. The current runtime uses pi-ai catalogs, SecretStorage credentials, and automatic model discovery. ## Overview diff --git a/docs/mutsumi_config_structure.json b/docs/mutsumi_config_structure.json index 9888f89..7ff34e8 100644 --- a/docs/mutsumi_config_structure.json +++ b/docs/mutsumi_config_structure.json @@ -1,78 +1,30 @@ { - "mutsumi.providers": [ - { - "name": "moonshotai", - "baseurl": "https://api.moonshot.cn/v1", - "api_key": "sk-XXX" - }, - { - "name": "deepseek", - "baseurl": "https://api.deepseek.com", - "api_key": "sk-XXX" - }, - { - "name": "kimi-for-coding", - "baseurl": "https://api.kimi.com/coding/v1", - "api_key": "sk-kimi-XXX" - }, - { - "name": "ZenMux", - "baseurl": "https://zenmux.ai/api/v1", - "api_key": "sk-ss-v1-XXX" + "mutsumi.customProviders": { + "ZenMux": { + "displayName": "ZenMux", + "baseUrl": "https://zenmux.ai/api/v1", + "api": "openai-completions", + "auth": "apiKey", + "models": [ + "z-ai/glm-5.2" + ] } - ], - "mutsumi.defaultModel": { - "provider": "kimi-for-coding", + }, + "mutsumi.defaultModel": { + "provider": "kimi-coding", "model": "kimi-for-coding" }, "mutsumi.titleGeneratorModel": { - "provider": "kimi-for-coding", + "provider": "kimi-coding", "model": "kimi-for-coding" }, "mutsumi.compressModel": { "provider": "ZenMux", "model": "z-ai/glm-5.2" }, - "mutsumi.models": { - "ZenMux": [ - "openai/gpt-4.1-nano", - "openai/gpt-5.6-sol", - "openai/gpt-5.6-terra", - "openai/gpt-5.6-luna", - "minimax/minimax-m2.7-highspeed", - "minimax/minimax-m3", - "z-ai/glm-5.2", - "moonshotai/kimi-k2.5", - "moonshotai/kimi-k2.6", - "moonshotai/kimi-k2.7-code", - "moonshotai/kimi-k2.7-code-highspeed", - "moonshotai/kimi-k3", - "deepseek/deepseek-v4-flash", - "deepseek/deepseek-v4-pro", - "stepfun/step-3.7-flash" - ], - "moonshotai": [ - "kimi-k2.6", - "kimi-k2.7-code", - "kimi-k2.7-code-highspeed", - "kimi-k3" - ], - "kimi-for-coding": [ - "kimi-for-coding", - "k3-256k", - "k3" - ], - "deepseek": [ - "deepseek-v4-flash", - "deepseek-v4-pro" - ] - }, + "_comment": "Configure LLM API keys with Mutsumi: Manage Model Providers. Keys are stored in VS Code SecretStorage and never belong in this JSON.", "mutsumi.httpServer.password": "XXX", "mutsumi.mcpServers": { - "tavily": { - "type": "http", - "url": "https://mcp.tavily.com/mcp?tavilyApiKey=tvly-dev-XXX" - }, "exa": { "type": "http", "url": "https://mcp.exa.ai/mcp", @@ -81,4 +33,4 @@ } } } -} \ No newline at end of file +} diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index a6d65dd..9af5404 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -104,7 +104,7 @@ "notebookController.displayName": "Mutsumi Agent", - "selectModel.noModels": "No models configured in settings.", + "selectModel.noModels": "No authenticated model provider is available.", "selectModel.placeHolder": "Select model or reasoning effort (switching model resets effort to default; current: {0} / {1})", "selectModel.modelChanged": "Model changed to: {0}; reasoning effort reset to default.", "selectModel.effortChanged": "Reasoning effort changed to: {0}", @@ -120,6 +120,53 @@ "selectModel.effort.high": "High reasoning", "selectModel.effort.xhigh": "Extra-high reasoning", "selectModel.effort.max": "Maximum reasoning", + "selectModel.loading": "Loading available models...", + "selectModel.loadFailed": "Failed to load models: {0}", + "selectModel.manageProviders": "Manage Providers", + + "providers.title": "Mutsumi Model Providers", + "providers.choose": "Choose a provider to configure", + "providers.deviceCode": "Code: {0}", + "providers.displayName": "Provider display name", + "providers.baseUrl": "OpenAI-compatible base URL", + "providers.httpUrl": "Use an HTTP(S) URL", + "providers.validUrl": "Enter a valid URL", + "providers.openaiCompletions": "OpenAI Chat Completions", + "providers.openaiResponses": "OpenAI Responses", + "providers.protocol": "Wire protocol", + "providers.noAuth": "No authentication", + "providers.authentication": "Authentication", + "providers.manualModels": "Manual fallback model IDs", + "providers.manualModelsPrompt": "Optional comma-separated IDs used when /models discovery is unavailable", + "providers.savedDiscoveryFailed": "Provider saved, but model discovery failed: {0}", + "providers.routeId": "Custom provider route ID", + "providers.routeIdPrompt": "Stable ID stored in agent files", + "providers.routeIdRequired": "Enter a non-empty route ID", + "providers.routeIdExists": "That route ID already exists", + "providers.added": "Provider \"{0}\" added.", + "providers.removeConfirm": "Remove custom provider \"{0}\", its stored credential, and cached models?", + "providers.remove": "Remove", + "providers.refresh": "Refresh models", + "providers.configureKey": "Configure or update API key", + "providers.removeCredential": "Remove stored credential", + "providers.edit": "Edit custom provider", + "providers.removeCustom": "Remove custom provider", + "providers.authenticatedBy": "Authenticated by {0}", + "providers.notConfigured": "Not configured", + "providers.credentialStored": "Credential stored securely for \"{0}\".", + "providers.credentialRemoved": "Stored credential removed for \"{0}\". Environment credentials may still apply.", + "providers.refreshed": "Models refreshed for \"{0}\".", + "providers.modelCountSource": "{0} models • {1}", + "providers.modelCountUnconfigured": "{0} models • API key not configured", + "providers.addCustom": "Add custom OpenAI-compatible provider", + "providers.failed": "Provider management failed: {0}", + "migration.conflicts": "Different plaintext keys exist for the same global route: {0}. Rename those routes or keep one key before migrating.", + "migration.routeConflicts": "Legacy custom routes conflict with built-in provider IDs: {0}. Rename those routes before migrating.", + "migration.rotationWarning": "Provider keys were moved to VS Code SecretStorage. Rotate any key that was committed to workspace or version-control history.", + "migration.noneFound": "No legacy plaintext provider credentials were found.", + "migration.failed": "Provider credential migration failed: {0}", + "migration.action": "Migrate securely", + "migration.prompt": "Mutsumi found plaintext LLM API keys in settings. Move them to VS Code SecretStorage now?", "renameSession.prompt": "Enter new session title (leave empty to auto-generate)", "renameSession.renamed": "Session renamed: {0}", diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index 8ce5fd1..1a1ac4c 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -104,7 +104,7 @@ "notebookController.displayName": "Mutsumi Agent", - "selectModel.noModels": "设置中未配置任何模型。", + "selectModel.noModels": "当前没有已鉴权且可用的模型提供商。", "selectModel.placeHolder": "选择模型或推理强度(切换模型会将强度重置为默认;当前: {0} / {1})", "selectModel.modelChanged": "模型已切换为: {0};推理强度已重置为默认。", "selectModel.effortChanged": "推理强度已切换为: {0}", @@ -120,6 +120,53 @@ "selectModel.effort.high": "高推理", "selectModel.effort.xhigh": "超高推理", "selectModel.effort.max": "最大推理", + "selectModel.loading": "正在加载可用模型...", + "selectModel.loadFailed": "加载模型失败:{0}", + "selectModel.manageProviders": "管理提供商", + + "providers.title": "Mutsumi 模型提供商", + "providers.choose": "选择要配置的提供商", + "providers.deviceCode": "设备代码:{0}", + "providers.displayName": "提供商显示名称", + "providers.baseUrl": "OpenAI-compatible 基础 URL", + "providers.httpUrl": "请使用 HTTP(S) URL", + "providers.validUrl": "请输入有效 URL", + "providers.openaiCompletions": "OpenAI Chat Completions", + "providers.openaiResponses": "OpenAI Responses", + "providers.protocol": "传输协议", + "providers.noAuth": "无需鉴权", + "providers.authentication": "鉴权方式", + "providers.manualModels": "手工回退模型 ID", + "providers.manualModelsPrompt": "可选;以逗号分隔,在 /models 自动发现不可用时使用", + "providers.savedDiscoveryFailed": "提供商已保存,但模型发现失败:{0}", + "providers.routeId": "自定义提供商路由 ID", + "providers.routeIdPrompt": "保存在 Agent 文件中的稳定标识", + "providers.routeIdRequired": "请输入非空路由 ID", + "providers.routeIdExists": "该路由 ID 已存在", + "providers.added": "已添加提供商“{0}”。", + "providers.removeConfirm": "删除自定义提供商“{0}”、其已存凭据和模型缓存吗?", + "providers.remove": "删除", + "providers.refresh": "刷新模型", + "providers.configureKey": "配置或更新 API Key", + "providers.removeCredential": "删除已存凭据", + "providers.edit": "编辑自定义提供商", + "providers.removeCustom": "删除自定义提供商", + "providers.authenticatedBy": "凭据来源:{0}", + "providers.notConfigured": "尚未配置", + "providers.credentialStored": "已为“{0}”安全存储凭据。", + "providers.credentialRemoved": "已删除“{0}”的存储凭据;环境凭据仍可能生效。", + "providers.refreshed": "已刷新“{0}”的模型。", + "providers.modelCountSource": "{0} 个模型 • {1}", + "providers.modelCountUnconfigured": "{0} 个模型 • 尚未配置 API Key", + "providers.addCustom": "添加自定义 OpenAI-compatible 提供商", + "providers.failed": "提供商管理失败:{0}", + "migration.conflicts": "同一全局路由存在不同的明文密钥:{0}。请先重命名路由或仅保留一个密钥,再执行迁移。", + "migration.routeConflicts": "旧版自定义路由与内置提供商 ID 冲突:{0}。请先重命名这些路由,再执行迁移。", + "migration.rotationWarning": "提供商密钥已迁移到 VS Code SecretStorage。若密钥曾提交到工作区或版本历史,请在服务商侧轮换。", + "migration.noneFound": "未发现旧版明文提供商凭据。", + "migration.failed": "提供商凭据迁移失败:{0}", + "migration.action": "安全迁移", + "migration.prompt": "Mutsumi 在设置中发现了明文 LLM API Key。现在将其迁移到 VS Code SecretStorage 吗?", "renameSession.prompt": "输入新的会话标题(留空则自动生成)", "renameSession.renamed": "会话已重命名: {0}", diff --git a/package-lock.json b/package-lock.json index 14dd3ff..e2b727a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "web-tree-sitter": "^0.22.2" }, "devDependencies": { + "@earendil-works/pi-ai": "^0.82.1", "@electron/rebuild": "^4.0.3", "@modelcontextprotocol/sdk": "^1.30.0", "@types/better-sqlite3": "^7.6.13", @@ -36,16 +37,537 @@ "micromark": "^4.0.0", "micromark-extension-gfm": "^2.0.0", "npm-run-all": "^4.1.5", - "openai": "^6.17.0", "partial-json": "^0.1.7", "preprocess": "^3.2.0", "typescript": "^5.9.3", - "uuid": "^9.0.1" + "uuid": "^9.0.1", + "vitest": "^3.2.7" }, "engines": { "vscode": "^1.108.0" } }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.91.1", + "integrity": "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime": { + "version": "3.1048.0", + "integrity": "sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/credential-provider-node": "^3.972.42", + "@aws-sdk/eventstream-handler-node": "^3.972.16", + "@aws-sdk/middleware-eventstream": "^3.972.12", + "@aws-sdk/middleware-websocket": "^3.972.19", + "@aws-sdk/token-providers": "3.1048.0", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.977.7", + "integrity": "sha512-I88Iov89NVmjSmJLKSv7Cn9M2J+a2942OkA8nZCbz+sl4ZeY4zEOcoLOrbt1GRfQ8zEQKnjAJdXixA3J/p1fDQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.3", + "@aws-sdk/xml-builder": "^3.972.38", + "@aws/lambda-invoke-store": "^0.3.0", + "@smithy/core": "^3.31.1", + "@smithy/signature-v4": "^5.6.12", + "@smithy/types": "^4.16.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.68", + "integrity": "sha512-2a20A/IdNOwUvaDq91iqqS7BA0XlNMfW3iLGZGZLJv0EbUqhSxB0PIx4rQQqssvWj1uXImb3/UCCdHz/+1dOiA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.70", + "integrity": "sha512-0yRem2Fs52r/Nn6UAqIlpjexfaYj8ziEozOe9tamtAVT/5bzFLKx8O2r7MaRqgS3hGKHIa1Jij9nKHSsNnb04A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/fetch-http-handler": "^5.6.13", + "@smithy/node-http-handler": "^4.9.13", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler": { + "version": "4.11.0", + "integrity": "sha512-ssHIZsadPUA3lGdnoByxfnjtb9xPYQLvdfJRLKIwxOoa6tO1suG4sLFSsgd7D/CsvYd8QbBIuKTImuJha5l6aQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.33.0", + "@smithy/types": "^4.17.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.973.13", + "integrity": "sha512-2M39DE02XpYYaSWYk/4AsImXYUU/1L2xmTMLUpMMWq7DfLv191/vCRy3baKtdr45AkJQyVgSjmuVOLm15SwrRQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/credential-provider-env": "^3.972.68", + "@aws-sdk/credential-provider-http": "^3.972.70", + "@aws-sdk/credential-provider-login": "^3.972.75", + "@aws-sdk/credential-provider-process": "^3.972.68", + "@aws-sdk/credential-provider-sso": "^3.973.12", + "@aws-sdk/credential-provider-web-identity": "^3.972.74", + "@aws-sdk/nested-clients": "^3.997.42", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/credential-provider-imds": "^4.4.16", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.75", + "integrity": "sha512-jaTESuJlQsoUZ44f/i2puyPt8VlF/dMMJ9HM3cStYtk7eKX4N9UWi83OLixUkoOJH3BwWlPLCq9YIK9nfWhVBg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/nested-clients": "^3.997.42", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.79", + "integrity": "sha512-RIw5dof1EHkWubrZzPC941CDtnFG1iAXsxbFgLkhdYZXHc4icU13c/uxSMI0J5eUx9bxa7LjfpdjfClBB1QsDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.68", + "@aws-sdk/credential-provider-http": "^3.972.70", + "@aws-sdk/credential-provider-ini": "^3.973.13", + "@aws-sdk/credential-provider-process": "^3.972.68", + "@aws-sdk/credential-provider-sso": "^3.973.12", + "@aws-sdk/credential-provider-web-identity": "^3.972.74", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/credential-provider-imds": "^4.4.16", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.68", + "integrity": "sha512-nLP3Pda2MQTFJ25hKBMmUuB9Uv+bTZQNlufbeCwklP549Vwnkd8bRLJoCKp5k6xjmdyptrPrOfGOhN0mKuca8A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.973.12", + "integrity": "sha512-EmgyyHn+f9WCcelp3L/vci+LGbX8GigWaVphRArjVo5Pktkr9YnLy/mQ6VDkDyBD72dtfRNTgHmD2ts4rTDXKQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/nested-clients": "^3.997.42", + "@aws-sdk/token-providers": "3.1108.0", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { + "version": "3.1108.0", + "integrity": "sha512-rI80zxDxGJ6904eC/YbjkdjY6JdaZvQ01kOmrMvw7cFQGIHo27fhnIVbMSVDS4T6foQImjxYSRoOu/uSJscXDw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/nested-clients": "^3.997.42", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.74", + "integrity": "sha512-0YfczxGXF3RjGj8z7QG/Ho2HnLGKDHfPSHiTs47UU1U/+mmwISDN+rvGKt2zh+3FX8NdT4xd95LGBGyhQw2dgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/nested-clients": "^3.997.42", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/eventstream-handler-node": { + "version": "3.972.32", + "integrity": "sha512-rlbmsMG7ZNgrVhWSqqXpq6y9hfiREyzCg3CNTk9UK+AoP7+65kOkqpWmqwLfV1UrRSHATdLnZF2rt9ZTUxYQJA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-eventstream": { + "version": "3.972.27", + "integrity": "sha512-M7Ay1VpBpf/YFfic9kkjwE3wyCh4G0gEM4RypRXYm7aPjyfqi+D8FEYMR2E3IqbvN+qi2rEFYAiwWL0XHtQYdQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket": { + "version": "3.972.50", + "integrity": "sha512-gdcWRbmIf1dWA/prf44Bnnzgqj+AbsXX2yfhZhOQLwSm7NfKIYPmkRlPqP0CTepHzjxMIBdWBDdtQB+Y/dFUeg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/fetch-http-handler": "^5.6.13", + "@smithy/signature-v4": "^5.6.12", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.997.42", + "integrity": "sha512-XWRyon2MTHXD/zMoo0Mbge6Vwf+iE0qQaM/RyGO6NfZ9WukCFiQL27nQVZjYy2JwSIg+iXZxKOX95OBXqlSM4w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.977.7", + "@aws-sdk/signature-v4-multi-region": "^3.996.44", + "@aws-sdk/types": "^3.974.3", + "@smithy/core": "^3.31.1", + "@smithy/fetch-http-handler": "^5.6.13", + "@smithy/node-http-handler": "^4.9.13", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler": { + "version": "4.11.0", + "integrity": "sha512-ssHIZsadPUA3lGdnoByxfnjtb9xPYQLvdfJRLKIwxOoa6tO1suG4sLFSsgd7D/CsvYd8QbBIuKTImuJha5l6aQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.33.0", + "@smithy/types": "^4.17.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.44", + "integrity": "sha512-ZSfQ35Qn4MhSY+A0Whyr+KBx+wJKZUyBsOrjB2pSHOafRzbFe47T8XcXM8hZqUAC69qnqIy0C9ArxTuud0CC2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.3", + "@smithy/signature-v4": "^5.6.12", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1048.0", + "integrity": "sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/nested-clients": "^3.997.9", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.974.3", + "integrity": "sha512-ECAqfpNsef+7MO8qtR0h9KcFIBAygaE7Cm6UOiQl+ft+uVap+1G7bNEjs4mdJE2OnA4m6k7i8peH8uGIAsOMGw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.9", + "integrity": "sha512-wB/ho7pTJKqWz3WYDt2ZWDWI8bxQpN/xwf+5ZQ1zWaj+HDY9B8Fn434i6qZ6j6ZG3aCiIJtZaQVqwajx5xYsQA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.38", + "integrity": "sha512-grf7mzfVxBS5AlsuTvBN7uDpzqohFww9fRPCO+EBSUdvtsYMcPSKdz54h/7XiscqNcUM1Ae1MF7JLHmiYYuzbQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.3.0", + "integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@earendil-works/pi-ai": { + "version": "0.82.1", + "integrity": "sha512-3WFYRhEp3lQB3444EhPMBcM7zSaEUE3eJgHOR7s4081NLqbw/FsWilIKWXSua0Gv3sRr7m9xMidR3pPDE7jI/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@anthropic-ai/sdk": "0.91.1", + "@aws-sdk/client-bedrock-runtime": "3.1048.0", + "@google/genai": "1.52.0", + "@mistralai/mistralai": "2.2.6", + "@opentelemetry/api": "1.9.0", + "@smithy/node-http-handler": "4.7.3", + "http-proxy-agent": "7.0.2", + "https-proxy-agent": "7.0.6", + "openai": "6.26.0", + "partial-json": "0.1.7", + "typebox": "1.1.38" + }, + "bin": { + "pi-ai": "dist/cli.js" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@earendil-works/pi-ai/node_modules/agent-base": { + "version": "7.1.4", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@earendil-works/pi-ai/node_modules/http-proxy-agent": { + "version": "7.0.2", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@earendil-works/pi-ai/node_modules/https-proxy-agent": { + "version": "7.0.6", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@electron/get": { "version": "2.0.3", "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", @@ -998,11 +1520,35 @@ "dev": true, "license": "MIT" }, - "node_modules/@hono/node-server": { - "version": "2.1.0", - "integrity": "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==", + "node_modules/@google/genai": { + "version": "1.52.0", + "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@hono/node-server": { + "version": "2.1.0", + "integrity": "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==", + "dev": true, + "license": "MIT", "engines": { "node": ">=20" }, @@ -1079,6 +1625,12 @@ "node": ">=18.0.0" } }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, "node_modules/@malept/cross-spawn-promise": { "version": "2.0.0", "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", @@ -1101,6 +1653,26 @@ "node": ">= 12.13.0" } }, + "node_modules/@mistralai/mistralai": { + "version": "2.2.6", + "integrity": "sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.40.0", + "ws": "^8.18.0", + "zod": "^3.25.0 || ^4.0.0", + "zod-to-json-schema": "^3.25.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + } + } + }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.30.0", "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", @@ -1141,6 +1713,25 @@ } } }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, "node_modules/@npmcli/agent": { "version": "3.0.0", "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", @@ -1239,1350 +1830,1535 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "dev": true, - "license": "MIT", - "optional": true, + "license": "Apache-2.0", "engines": { - "node": ">=14" + "node": ">=8.0.0" } }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node": ">=14" } }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, + "optional": true, "engines": { - "node": ">=10" + "node": ">=14" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/better-sqlite3": { - "version": "7.6.13", - "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/connect": { - "version": "3.4.38", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@types/node": "*" + "@protobufjs/aspromise": "^1.1.1" } }, - "node_modules/@types/debug": { - "version": "4.1.13", - "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/diff": { - "version": "8.0.0", - "integrity": "sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw==", - "deprecated": "This is a stub types definition. diff provides its own type definitions, so you do not need this installed.", + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", "dev": true, - "license": "MIT", - "dependencies": { - "diff": "*" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/express": { - "version": "5.0.6", - "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "^2" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/express-serve-static-core": { - "version": "5.1.1", - "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } + "license": "BSD-3-Clause" }, - "node_modules/@types/hast": { - "version": "3.0.5", - "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.4", + "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "*" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@types/http-cache-semantics": { - "version": "4.2.0", - "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.4", + "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.4", + "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.4", + "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.4", + "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "*" - } + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@types/ms": { - "version": "2.1.0", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.4", + "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@types/node": { - "version": "18.19.130", - "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.4", + "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==", + "cpu": [ + "arm" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/node-notifier": { - "version": "8.0.5", - "integrity": "sha512-LX7+8MtTsv6szumAp6WOy87nqMEdGhhry/Qfprjm1Ma6REjVzeF7SCyvPtp5RaF6IkXCS9V4ra8g5fwvf2ZAYg==", + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.4", + "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==", + "cpu": [ + "arm" + ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/qs": { - "version": "6.14.0", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.4", + "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.4", + "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.4", + "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==", + "cpu": [ + "loong64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/send": { - "version": "1.2.1", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.4", + "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==", + "cpu": [ + "loong64" + ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/serve-static": { - "version": "2.2.0", - "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.4", + "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==", + "cpu": [ + "ppc64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/unist": { - "version": "3.0.3", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.4", + "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MIT" + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.4", + "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT" + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/vscode": { - "version": "1.108.1", - "integrity": "sha512-DerV0BbSzt87TbrqmZ7lRDIYaMiqvP8tmJTzW2p49ZBVtGUnGAu2RGQd1Wv4XMzEVUpaHbsemVM5nfuQJj7H6w==", + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.4", + "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT" + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.4", + "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==", + "cpu": [ + "s390x" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, - "dependencies": { - "@types/node": "*" - } + "os": [ + "linux" + ] }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.3", - "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.4", + "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC" + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/abbrev": { - "version": "1.1.1", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.4", + "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC" + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/accepts": { - "version": "2.0.0", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.4", + "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.4", + "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.4", + "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.4", + "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.4", + "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.4", + "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "dev": true, "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/@smithy/core": { + "version": "3.33.0", + "integrity": "sha512-uKbkxgqLyepQDZoq8aRSdUqD1ID//rOqG96ixBhp++O7vBtmwYM6fwldGhr9HJP0iYrdc7GP/AlgzPWEZIrNRg==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "debug": "4" + "@smithy/types": "^4.17.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 6.0.0" + "node": ">=18.0.0" } }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "node_modules/@smithy/credential-provider-imds": { + "version": "4.5.0", + "integrity": "sha512-2jsPi+7Zv2hSzD9IXR9D7DTqSn7mv4XalzRm+bESh53jiaUS3NKEUbpQFTJP0HhQy9qzZvluxQ3yS24zdRrqsA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "humanize-ms": "^1.2.1" + "@smithy/core": "^3.32.0", + "@smithy/types": "^4.17.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 8.0.0" + "node": ">=18.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@smithy/fetch-http-handler": { + "version": "5.7.0", + "integrity": "sha512-W/exA8T0LEzCQtJ02w4IzaEQPIspgarqZprb7W8FwnYiDowgCrjl2fTQ6FvuSSUnJORuepBF81abmBJwqh+0XQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "@smithy/core": "^3.32.0", + "@smithy/types": "^4.17.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" + "node": ">=18.0.0" } }, - "node_modules/ajv": { - "version": "8.20.0", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "tslib": "^2.6.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "node_modules/@smithy/node-http-handler": { + "version": "4.7.3", + "integrity": "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=18.0.0" } }, - "node_modules/ansi-styles": { - "version": "6.2.3", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "node_modules/@smithy/signature-v4": { + "version": "5.7.0", + "integrity": "sha512-hCynhm22wMJ8wTF9crcwu8mxggtUrSLLJgDcGUvYFBqpofxycYJCGKOMYg4xtPPFtgNiDJSYmhsWLTrcU/g59Q==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.32.0", + "@smithy/types": "^4.17.0", + "tslib": "^2.6.2" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/aproba": { - "version": "2.1.0", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "dev": true, - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", + "node_modules/@smithy/types": { + "version": "4.17.0", + "integrity": "sha512-Aw4joiM0ZdErpo39lCj8phT2lxoiKZV+KZzBxnnQhWVtU2Is/WffQSL04uUWRcXUse9Ln8vXZK6V/FwqRVnQpg==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" + "tslib": "^2.6.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=18.0.0" } }, - "node_modules/argparse": { - "version": "1.0.10", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "sprintf-js": "~1.0.2" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.0.0" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" + "defer-to-connect": "^2.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/async-function": { - "version": "1.0.0", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">= 10" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", "dev": true, "license": "MIT", "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/node": "*" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/@types/body-parser": { + "version": "1.19.6", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dev": true, - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/better-sqlite3": { - "version": "12.8.0", - "integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==", - "hasInstallScript": true, "license": "MIT", "dependencies": { - "bindings": "^1.5.0", - "prebuild-install": "^7.1.1" - }, - "engines": { - "node": "20.x || 22.x || 23.x || 24.x || 25.x" + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/bindings": { - "version": "1.5.0", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, "license": "MIT", "dependencies": { - "file-uri-to-path": "1.0.0" + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" } }, - "node_modules/bl": { - "version": "4.1.0", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@types/chai": { + "version": "5.2.3", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, "license": "MIT", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/body-parser": { - "version": "2.2.2", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "node_modules/@types/connect": { + "version": "3.4.38", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "@types/node": "*" } }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.7.3", - "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "node_modules/@types/debug": { + "version": "4.1.13", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "@types/ms": "*" } }, - "node_modules/boolean": { - "version": "3.2.0", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/diff": { + "version": "8.0.0", + "integrity": "sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw==", + "deprecated": "This is a stub types definition. diff provides its own type definitions, so you do not need this installed.", "dev": true, "license": "MIT", - "optional": true + "dependencies": { + "diff": "*" + } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@types/estree": { + "version": "1.0.9", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.6", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" } }, - "node_modules/buffer": { - "version": "5.7.1", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "dev": true, "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/@types/hast": { + "version": "3.0.5", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", "dev": true, "license": "MIT", - "engines": { - "node": "*" + "dependencies": { + "@types/unist": "*" } }, - "node_modules/bytes": { - "version": "3.1.2", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "license": "MIT" }, - "node_modules/cacache": { - "version": "16.1.3", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "node_modules/@types/http-errors": { + "version": "2.0.5", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "dev": true, - "license": "ISC", + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "@types/node": "*" } }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.2", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "node_modules/@types/mdast": { + "version": "4.0.4", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "@types/unist": "*" } }, - "node_modules/cacache/node_modules/chownr": { - "version": "2.0.0", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "node_modules/@types/ms": { + "version": "2.1.0", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/@types/node": { + "version": "18.19.130", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "undici-types": "~5.26.4" } }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.9", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "node_modules/@types/node-notifier": { + "version": "8.0.5", + "integrity": "sha512-LX7+8MtTsv6szumAp6WOy87nqMEdGhhry/Qfprjm1Ma6REjVzeF7SCyvPtp5RaF6IkXCS9V4ra8g5fwvf2ZAYg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" + "@types/node": "*" } }, - "node_modules/cacache/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/@types/qs": { + "version": "6.14.0", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "dev": true, - "license": "ISC", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@types/node": "*" } }, - "node_modules/cacache/node_modules/minizlib": { - "version": "2.1.2", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/@types/retry": { + "version": "0.12.0", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" + "@types/node": "*" } }, - "node_modules/cacache/node_modules/tar": { - "version": "6.2.1", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "node_modules/@types/serve-static": { + "version": "2.2.0", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@types/http-errors": "*", + "@types/node": "*" } }, - "node_modules/cacache/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/@types/unist": { + "version": "3.0.3", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/vscode": { + "version": "1.108.1", + "integrity": "sha512-DerV0BbSzt87TbrqmZ7lRDIYaMiqvP8tmJTzW2p49ZBVtGUnGAu2RGQd1Wv4XMzEVUpaHbsemVM5nfuQJj7H6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/cacache/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", "dev": true, "license": "ISC" }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "node_modules/@vitest/expect": { + "version": "3.2.7", + "integrity": "sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10.6.0" + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.7", + "@vitest/utils": "3.2.7", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "node_modules/@vitest/pretty-format": { + "version": "3.2.7", + "integrity": "sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA==", "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" + "tinyrainbow": "^2.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/call-bind": { - "version": "1.0.8", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "node_modules/@vitest/runner": { + "version": "3.2.7", + "integrity": "sha512-sB9y4ovltoQP+WaUPwmSxO9WIg9Ig694Di5PalVPsYHklAdE027mehpWF2SQSVq+k6sFgaivbTjTJwZLSHbedA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" + "@vitest/utils": "3.2.7", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/@vitest/snapshot": { + "version": "3.2.7", + "integrity": "sha512-7C+MwShwtBSI5Buwoyg3s/iY1eHL9PKAf+O1wVh/TdnjXUtkoL/9YQtre90i4MtNXM6edP1wJ2zOBpfCyhIS7g==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "@vitest/pretty-format": "3.2.7", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "node_modules/@vitest/spy": { + "version": "3.2.7", + "integrity": "sha512-Q2eQGI6d2L/hBtZ0qNuKcAGid68XK6cv1xsoaIma6PaJhHPoqcEJhYpXZ/5myCMqkNgtP6UKuBhbc0nHKnrkuQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" + "tinyspy": "^4.0.3" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/ccount": { - "version": "2.0.1", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "node_modules/@vitest/utils": { + "version": "3.2.7", + "integrity": "sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw==", "dev": true, "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.7", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://opencollective.com/vitest" } }, - "node_modules/chalk": { - "version": "2.4.2", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/abbrev": { + "version": "1.1.1", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/accepts": { + "version": "2.0.0", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "3.2.1", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/agent-base": { + "version": "6.0.2", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "debug": "4" }, "engines": { - "node": ">=4" + "node": ">= 6.0.0" } }, - "node_modules/chalk/node_modules/color-convert": { - "version": "1.9.3", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/agentkeepalive": { + "version": "4.6.0", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" } }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.3", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, "engines": { - "node": ">=0.8.0" + "node": ">=8" } }, - "node_modules/chalk/node_modules/has-flag": { - "version": "3.0.0", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/ajv": { + "version": "8.20.0", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/ajv-formats": { + "version": "3.0.1", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "ajv": "^8.0.0" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/character-entities": { - "version": "2.0.2", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "node_modules/ansi-regex": { + "version": "6.2.2", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "node_modules/ansi-styles": { + "version": "6.2.3", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "node_modules/aproba": { + "version": "2.1.0", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "license": "ISC" }, - "node_modules/chownr": { - "version": "3.0.0", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, "engines": { - "node": ">=18" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/argparse": { + "version": "1.0.10", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cliui": { - "version": "8.0.1", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/assertion-error": { + "version": "2.0.1", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/async-function": { + "version": "1.0.0", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/balanced-match": { + "version": "1.0.2", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/better-sqlite3": { + "version": "12.8.0", + "integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==", + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" }, "engines": { - "node": ">=8" + "node": "20.x || 22.x || 23.x || 24.x || 25.x" } }, - "node_modules/clone": { - "version": "1.0.4", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/bignumber.js": { + "version": "9.3.1", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.8" + "node": "*" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, + "node_modules/bindings": { + "version": "1.5.0", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "license": "MIT", "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "file-uri-to-path": "1.0.0" } }, - "node_modules/clone-response/node_modules/mimic-response": { - "version": "1.0.1", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, + "node_modules/bl": { + "version": "4.1.0", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/body-parser": { + "version": "2.2.2", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/color-name": { - "version": "1.1.4", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-support": { - "version": "1.1.3", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.7.3", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "node_modules/boolean": { + "version": "3.2.0", + "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", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "optional": true }, - "node_modules/concat-map": { - "version": "0.0.1", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/bowser": { + "version": "2.14.1", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", "dev": true, "license": "MIT" }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "node_modules/brace-expansion": { + "version": "1.1.12", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/content-disposition": { - "version": "1.0.1", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", - "dev": true, + "node_modules/buffer": { + "version": "5.7.1", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/content-type": { - "version": "1.0.5", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/buffer-crc32": { + "version": "0.2.13", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": "*" } }, - "node_modules/cookie": { - "version": "0.7.2", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "node_modules/cac": { + "version": "6.7.14", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=6.6.0" + "node": ">=8" } }, - "node_modules/cors": { - "version": "2.8.6", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "node_modules/cacache": { + "version": "16.1.3", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" }, "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.2", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" + "balanced-match": "^1.0.0" } }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/cacache/node_modules/chownr": { + "version": "2.0.0", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, "engines": { - "node": ">= 8" + "node": ">=10" } }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dev": true, - "license": "MIT", + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.9", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" + "node": ">=10" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/debug": { - "version": "4.4.3", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/cacache/node_modules/minizlib": { + "version": "2.1.2", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/decode-named-character-reference": { - "version": "1.3.0", - "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "node_modules/cacache/node_modules/tar": { + "version": "6.2.1", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "character-entities": "^2.0.0" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=10" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, + "node_modules/cacache/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=4.0.0" + "node": ">=10.6.0" } }, - "node_modules/defaults": { - "version": "1.0.4", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/cacheable-request": { + "version": "7.0.4", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", "dev": true, "license": "MIT", "dependencies": { - "clone": "^1.0.2" + "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" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "node_modules/call-bind": { + "version": "1.0.8", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/call-bound": { + "version": "1.0.4", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -2591,643 +3367,492 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delegates": { - "version": "1.0.0", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/depd": { - "version": "2.0.0", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/ccount": { + "version": "2.0.1", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/dequal": { - "version": "2.0.3", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "node_modules/chai": { + "version": "5.3.3", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, "engines": { - "node": ">=6" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/devlop": { - "version": "1.1.0", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "node_modules/chalk": { + "version": "2.4.2", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", "dependencies": { - "dequal": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/diff": { - "version": "8.0.3", - "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", - "dev": true, - "license": "BSD-3-Clause", "engines": { - "node": ">=0.3.1" + "node": ">=4" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/chalk/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" + "node_modules/chalk/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } }, - "node_modules/ee-first": { - "version": "1.1.1", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, "license": "MIT" }, - "node_modules/electron": { - "version": "39.0.0", - "integrity": "sha512-UejnuOK4jpRZUq7MkEAnR/szsRWLKBJAdvn6j3xdQLT57fVv13VSNdaUHHjSheaqGzNhCGIdkPsPJnGJVh5kiA==", + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^22.7.7", - "extract-zip": "^2.0.1" - }, - "bin": { - "electron": "cli.js" - }, "engines": { - "node": ">= 12.20.55" + "node": ">=0.8.0" } }, - "node_modules/electron-rebuild": { - "version": "3.2.9", - "integrity": "sha512-FkEZNFViUem3P0RLYbZkUjC8LUFIK+wKq09GHoOITSJjfDAVQv964hwaNseTTWt58sITQX3/5fHNYcTefqaCWw==", - "deprecated": "Please use @electron/rebuild moving forward. There is no API change, just a package name change", + "node_modules/chalk/node_modules/has-flag": { + "version": "3.0.0", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "license": "MIT", - "dependencies": { - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "lzma-native": "^8.0.5", - "node-abi": "^3.0.0", - "node-api-version": "^0.1.4", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/src/cli.js" - }, "engines": { - "node": ">=12.13.0" + "node": ">=4" } }, - "node_modules/electron-rebuild/node_modules/ansi-regex": { - "version": "5.0.1", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/electron-rebuild/node_modules/ansi-styles": { - "version": "4.3.0", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/character-entities": { + "version": "2.0.2", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/electron-rebuild/node_modules/chalk": { - "version": "4.1.2", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/character-entities-html4": { + "version": "2.1.0", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", "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" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/electron-rebuild/node_modules/chownr": { - "version": "2.0.0", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/electron-rebuild/node_modules/cli-cursor": { - "version": "3.1.0", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/check-error": { + "version": "2.1.3", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "dev": true, "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, "engines": { - "node": ">=8" + "node": ">= 16" } }, - "node_modules/electron-rebuild/node_modules/fs-extra": { - "version": "10.1.0", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/chownr": { + "version": "3.0.0", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/electron-rebuild/node_modules/is-interactive": { - "version": "1.0.0", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "node_modules/clean-stack": { + "version": "2.2.0", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/electron-rebuild/node_modules/is-unicode-supported": { - "version": "0.1.0", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/electron-rebuild/node_modules/log-symbols": { - "version": "4.1.0", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/cliui": { + "version": "8.0.1", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/electron-rebuild/node_modules/minipass": { - "version": "5.0.0", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/electron-rebuild/node_modules/minizlib": { - "version": "2.1.2", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/electron-rebuild/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/electron-rebuild/node_modules/onetime": { - "version": "5.1.2", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/electron-rebuild/node_modules/ora": { - "version": "5.4.1", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/clone": { + "version": "1.0.4", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8" } }, - "node_modules/electron-rebuild/node_modules/restore-cursor": { - "version": "3.1.0", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/clone-response": { + "version": "1.0.3", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "mimic-response": "^1.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/electron-rebuild/node_modules/strip-ansi": { - "version": "6.0.1", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/electron-rebuild/node_modules/tar": { - "version": "6.2.1", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "node_modules/color-convert": { + "version": "2.0.1", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" + "node": ">=7.0.0" } }, - "node_modules/electron-rebuild/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/color-name": { + "version": "1.1.4", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/electron/node_modules/@types/node": { - "version": "22.19.15", - "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", + "node_modules/color-support": { + "version": "1.1.3", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/electron/node_modules/undici-types": { - "version": "6.21.0", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "node_modules/concat-map": { + "version": "0.0.1", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/console-control-strings": { + "version": "1.1.0", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/content-disposition": { + "version": "1.0.1", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/encoding": { - "version": "0.1.13", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "node_modules/content-type": { + "version": "1.0.5", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "node_modules/cookie": { + "version": "0.7.2", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/err-code": { - "version": "2.0.3", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.4", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "node_modules/cookie-signature": { + "version": "1.2.2", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "dev": true, "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "engines": { + "node": ">=6.6.0" } }, - "node_modules/es-abstract": { - "version": "1.24.1", - "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "node_modules/cors": { + "version": "2.8.6", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" + "object-assign": "^4", + "vary": "^1" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">= 0.4" + "node": ">= 8" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, "engines": { - "node": ">= 0.4" + "node": ">= 8" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, "engines": { - "node": ">= 0.4" + "node": ">= 12" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/data-view-buffer": { + "version": "1.0.2", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/esbuild": { - "version": "0.25.12", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escalade": { - "version": "3.2.0", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/debug": { + "version": "4.4.3", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=6" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/escape-html": { - "version": "1.0.3", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, + "node_modules/decompress-response": { + "version": "6.0.0", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "license": "MIT", - "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, "engines": { "node": ">=10" }, @@ -3235,424 +3860,419 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esprima": { - "version": "4.0.1", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/deep-eql": { + "version": "5.0.2", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/etag": { - "version": "1.8.1", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, + "node_modules/deep-extend": { + "version": "0.6.0", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=4.0.0" } }, - "node_modules/eventsource": { - "version": "3.0.7", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "node_modules/defaults": { + "version": "1.0.4", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "license": "MIT", "dependencies": { - "eventsource-parser": "^3.0.1" + "clone": "^1.0.2" }, - "engines": { - "node": ">=18.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eventsource-parser": { - "version": "3.1.0", - "integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==", + "node_modules/defer-to-connect": { + "version": "2.0.1", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, "license": "MIT", "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/express": { - "version": "5.2.1", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "node_modules/define-data-property": { + "version": "1.1.4", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": ">= 18" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express-rate-limit": { - "version": "8.6.2", - "integrity": "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==", + "node_modules/define-properties": { + "version": "1.2.1", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.4.3", - "ip-address": "^10.2.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">= 16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/delegates": { + "version": "1.0.0", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "node_modules/dequal": { + "version": "2.0.3", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "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" - }, + "license": "MIT", "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "node": ">=6" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.5", - "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" + "node_modules/detect-libc": { + "version": "2.1.2", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } }, - "node_modules/fd-slicer": { + "node_modules/detect-node": { + "version": "2.1.0", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/devlop": { "version": "1.1.0", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "dev": true, "license": "MIT", "dependencies": { - "pend": "~1.2.0" + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/fdir": { - "version": "6.5.0", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/diff": { + "version": "8.0.3", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" + "node": ">=0.3.1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "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" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "engines": { + "node": ">= 0.4" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, "license": "MIT" }, - "node_modules/finalhandler": { - "version": "2.1.1", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron": { + "version": "39.0.0", + "integrity": "sha512-UejnuOK4jpRZUq7MkEAnR/szsRWLKBJAdvn6j3xdQLT57fVv13VSNdaUHHjSheaqGzNhCGIdkPsPJnGJVh5kiA==", "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" + "@electron/get": "^2.0.0", + "@types/node": "^22.7.7", + "extract-zip": "^2.0.1" }, - "engines": { - "node": ">= 18.0.0" + "bin": { + "electron": "cli.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "engines": { + "node": ">= 12.20.55" } }, - "node_modules/for-each": { - "version": "0.3.5", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "node_modules/electron-rebuild": { + "version": "3.2.9", + "integrity": "sha512-FkEZNFViUem3P0RLYbZkUjC8LUFIK+wKq09GHoOITSJjfDAVQv964hwaNseTTWt58sITQX3/5fHNYcTefqaCWw==", + "deprecated": "Please use @electron/rebuild moving forward. There is no API change, just a package name change", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.2.7" + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^2.0.1", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "lzma-native": "^8.0.5", + "node-abi": "^3.0.0", + "node-api-version": "^0.1.4", + "node-gyp": "^9.0.0", + "ora": "^5.1.0", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" }, - "engines": { - "node": ">= 0.4" + "bin": { + "electron-rebuild": "lib/src/cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=12.13.0" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "node_modules/electron-rebuild/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, + "license": "MIT", "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/electron-rebuild/node_modules/ansi-styles": { + "version": "4.3.0", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=14" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/electron-rebuild/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fresh": { + "node_modules/electron-rebuild/node_modules/chownr": { "version": "2.0.0", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/electron-rebuild/node_modules/cli-cursor": { + "version": "3.1.0", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/electron-rebuild/node_modules/fs-extra": { + "version": "10.1.0", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/fs.realpath": { + "node_modules/electron-rebuild/node_modules/is-interactive": { "version": "1.0.0", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/function-bind": { - "version": "1.1.2", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/electron-rebuild/node_modules/is-unicode-supported": { + "version": "0.1.0", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "license": "MIT", + "engines": { + "node": ">=10" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "node_modules/electron-rebuild/node_modules/log-symbols": { + "version": "4.1.0", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "node_modules/electron-rebuild/node_modules/minipass": { + "version": "5.0.0", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-rebuild/node_modules/minizlib": { + "version": "2.1.2", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/gauge": { - "version": "4.0.4", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", + "node_modules/electron-rebuild/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "license": "ISC", "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" + "yallist": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/electron-rebuild/node_modules/onetime": { + "version": "5.1.2", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/electron-rebuild/node_modules/ora": { + "version": "5.4.1", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/electron-rebuild/node_modules/restore-cursor": { + "version": "3.1.0", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { "node": ">=8" } }, - "node_modules/gauge/node_modules/strip-ansi": { + "node_modules/electron-rebuild/node_modules/strip-ansi": { "version": "6.0.1", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, @@ -3664,221 +4284,230 @@ "node": ">=8" } }, - "node_modules/generator-function": { - "version": "2.0.1", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "node_modules/electron-rebuild/node_modules/tar": { + "version": "6.2.1", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/electron-rebuild/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } + "license": "ISC" }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/electron/node_modules/@types/node": { + "version": "22.19.15", + "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", "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" + "undici-types": "~6.21.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/electron/node_modules/undici-types": { + "version": "6.21.0", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8" } }, - "node_modules/get-stream": { - "version": "5.2.0", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/encoding": { + "version": "0.1.13", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "iconv-lite": "^0.6.2" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, + "node_modules/end-of-stream": { + "version": "1.4.5", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "node_modules/err-code": { + "version": "2.0.3", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, "license": "MIT" }, - "node_modules/glob": { - "version": "7.2.3", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/error-ex": { + "version": "1.3.4", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "is-arrayish": "^0.2.1" } }, - "node_modules/global-agent": { - "version": "3.0.0", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "node_modules/es-abstract": { + "version": "1.24.1", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", "dev": true, - "license": "BSD-3-Clause", - "optional": true, + "license": "MIT", "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" + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { - "node": ">=10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "node_modules/es-define-property": { + "version": "1.0.1", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", - "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", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/es-errors": { + "version": "1.3.0", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/got": { - "version": "11.8.6", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "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" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" } }, - "node_modules/growly": { + "node_modules/es-to-primitive": { "version": "1.3.0", - "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==", - "license": "MIT" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, "engines": { "node": ">= 0.4" }, @@ -3886,389 +4515,361 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/es6-error": { + "version": "4.1.1", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - } + "optional": true }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/esbuild": { + "version": "0.25.12", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" + "bin": { + "esbuild": "bin/esbuild" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/has-proto": { - "version": "1.2.0", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "node_modules/escalade": { + "version": "3.2.0", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/escape-html": { + "version": "1.0.3", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/esprima": { + "version": "4.0.1", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/estree-walker": { + "version": "3.0.3", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" + "@types/estree": "^1.0.0" } }, - "node_modules/hast-util-to-html": { - "version": "9.0.5", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "node_modules/etag": { + "version": "1.8.1", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.6" } }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "node_modules/eventsource": { + "version": "3.0.7", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0" + "eventsource-parser": "^3.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/highlight.js": { - "version": "11.11.1", - "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", - "dev": true, - "license": "BSD-3-Clause", "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, - "node_modules/hono": { - "version": "4.13.0", - "integrity": "sha512-jhunvfHWxd7J5EFfSgH4xsYJzSe/lfqbUCxiyyeaQasUsXeEHXtzVid+7EOGByc5JnFa23SSFL3Y2RV/z1T+eQ==", + "node_modules/eventsource-parser": { + "version": "3.1.0", + "integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==", "dev": true, "license": "MIT", "engines": { - "node": ">=16.9.0" + "node": ">=18.0.0" } }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" + "node_modules/expand-template": { + "version": "2.0.3", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "node_modules/expect-type": { + "version": "1.4.0", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" } }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "node_modules/exponential-backoff": { + "version": "3.1.3", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", "dev": true, - "license": "BSD-2-Clause" + "license": "Apache-2.0" }, - "node_modules/http-errors": { - "version": "2.0.1", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "node_modules/express": { + "version": "5.2.1", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "dev": true, "license": "MIT", "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "node_modules/express-rate-limit": { + "version": "8.6.2", + "integrity": "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==", "dev": true, "license": "MIT", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "debug": "^4.4.3", + "ip-address": "^10.2.0" }, "engines": { - "node": ">= 6" + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" } }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "node_modules/extend": { + "version": "3.0.2", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, "license": "MIT", "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=10.19.0" + "node": ">=0.10.0" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/extract-zip": { + "version": "2.0.1", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "agent-base": "6", - "debug": "4" + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" }, "engines": { - "node": ">= 6" + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } + "license": "MIT" }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/fast-uri": { + "version": "3.1.5", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "url": "https://github.com/sponsors/fastify" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "opencollective", + "url": "https://opencollective.com/fastify" } ], "license": "BSD-3-Clause" }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.8.19" + "dependencies": { + "pend": "~1.2.0" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/fdir": { + "version": "6.5.0", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, - "node_modules/inflight": { - "version": "1.0.6", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "1.3.8", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip-address": { - "version": "10.4.0", - "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "node_modules/fetch-blob": { + "version": "3.2.0", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^12.20 || >= 14.13" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "license": "MIT" }, - "node_modules/is-async-function": { + "node_modules/finalhandler": { "version": "2.1.1", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "dev": true, "license": "MIT", "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">= 18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/is-bigint": { - "version": "1.1.0", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "node_modules/for-each": { + "version": "0.3.5", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "license": "MIT", "dependencies": { - "has-bigints": "^1.0.2" + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -4277,131 +4878,140 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "node_modules/foreground-child": { + "version": "3.3.1", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "fetch-blob": "^3.1.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12.20.0" } }, - "node_modules/is-data-view": { - "version": "1.0.2", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "node_modules/forwarded": { + "version": "0.2.0", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } }, - "node_modules/is-date-object": { - "version": "1.1.0", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "node_modules/fresh": { + "version": "2.0.0", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" + "minipass": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "license": "MIT", - "bin": { - "is-docker": "cli.js" + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "node_modules/function-bind": { + "version": "1.1.2", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "node_modules/function.prototype.name": { + "version": "1.1.8", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -4410,95 +5020,163 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/is-map": { - "version": "2.0.3", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "node_modules/gauge": { + "version": "4.0.4", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "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" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/is-number-object": { - "version": "1.1.1", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" + } + }, + "node_modules/gaxios": { + "version": "7.3.1", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=18" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 14" + } }, - "node_modules/is-regex": { - "version": "1.2.1", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": ">= 0.4" + "node": ">= 14" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=18" } }, - "node_modules/is-set": { - "version": "2.0.3", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "node_modules/generator-function": { + "version": "2.0.1", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "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" @@ -4507,46 +5185,43 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-string": { - "version": "1.1.1", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "node_modules/get-proto": { + "version": "1.0.1", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-symbol": { - "version": "1.1.1", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "node_modules/get-stream": { + "version": "5.2.0", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" + "pump": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -4555,41 +5230,58 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "node_modules/github-from-package": { + "version": "0.0.0", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">= 0.4" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-weakref": { - "version": "1.1.1", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "node_modules/global-agent": { + "version": "3.0.0", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", + "optional": true, "dependencies": { - "call-bound": "^1.0.3" + "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": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.0" } }, - "node_modules/is-weakset": { - "version": "2.0.4", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "node_modules/globalthis": { + "version": "1.0.4", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -4598,584 +5290,2134 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "license": "MIT", + "node_modules/google-auth-library": { + "version": "10.9.1", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "is-docker": "^2.0.0" + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/isarray": { - "version": "2.0.5", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "node_modules/google-logging-utils": { + "version": "1.1.3", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "license": "Apache-2.0", + "engines": { + "node": ">=14" } }, - "node_modules/jose": { - "version": "6.2.8", - "integrity": "sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==", + "node_modules/gopd": { + "version": "1.2.0", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { - "url": "https://github.com/sponsors/panva" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/js-yaml": { - "version": "3.14.2", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/got": { + "version": "11.8.6", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@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" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "node_modules/gray-matter": { + "version": "4.0.3", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, + "node_modules/growly": { + "version": "1.3.0", + "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==", "license": "MIT" }, - "node_modules/json-schema-typed": { - "version": "8.0.2", - "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "node_modules/has-bigints": { + "version": "1.1.0", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, - "license": "BSD-2-Clause" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "node_modules/has-flag": { + "version": "4.0.0", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "ISC", - "optional": true + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/jsonfile": { - "version": "6.2.0", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "es-define-property": "^1.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/keyv": { - "version": "4.5.4", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/has-proto": { + "version": "1.2.0", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/has-symbols": { + "version": "1.1.0", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/kleur": { - "version": "4.1.5", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/load-json-file": { - "version": "4.0.0", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "node_modules/has-unicode": { + "version": "2.0.1", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.2", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lowlight": { - "version": "3.3.0", - "integrity": "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==", + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.0.0", - "highlight.js": "~11.11.0" + "@types/hast": "^3.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lru-cache": { - "version": "7.18.3", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/highlight.js": { + "version": "11.11.1", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "engines": { - "node": ">=12" + "node": ">=12.0.0" } }, - "node_modules/lzma-native": { - "version": "8.0.6", - "integrity": "sha512-09xfg67mkL2Lz20PrrDeNYZxzeW7ADtpYFbwSQh9U8+76RIzx5QsJBMy8qikv3hbUPfpy6hqwxt6FcGK81g9AA==", + "node_modules/hono": { + "version": "4.13.0", + "integrity": "sha512-jhunvfHWxd7J5EFfSgH4xsYJzSe/lfqbUCxiyyeaQasUsXeEHXtzVid+7EOGByc5JnFa23SSFL3Y2RV/z1T+eQ==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "dependencies": { - "node-addon-api": "^3.1.0", - "node-gyp-build": "^4.2.1", - "readable-stream": "^3.6.0" - }, - "bin": { - "lzmajs": "bin/lzmajs" - }, "engines": { - "node": ">=10.0.0" + "node": ">=16.9.0" } }, - "node_modules/lzma-native/node_modules/node-addon-api": { - "version": "3.2.1", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "node_modules/hosted-git-info": { + "version": "2.8.9", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "node_modules/html-void-elements": { + "version": "3.0.0", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", "dev": true, - "license": "ISC", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/make-fetch-happen/node_modules/negotiator": { - "version": "0.6.4", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "node_modules/http2-wrapper": { + "version": "1.0.3", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", "dev": true, "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10.19.0" } }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } }, - "node_modules/matcher": { - "version": "3.0.0", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "node_modules/humanize-ms": { + "version": "1.2.1", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "escape-string-regexp": "^4.0.0" + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "node_modules/ieee754": { + "version": "1.2.1", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=0.8.19" } }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "node_modules/indent-string": { + "version": "4.0.0", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true, + "license": "ISC" + }, + "node_modules/inflight": { + "version": "1.0.6", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/media-typer": { + "node_modules/inherits": { + "version": "2.0.4", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/internal-slot": { "version": "1.1.0", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" } }, - "node_modules/memorystream": { - "version": "0.3.1", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "node_modules/ip-address": { + "version": "10.4.0", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.10.0" + "node": ">= 12" } }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "node_modules/ipaddr.js": { + "version": "1.9.1", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.10" } }, - "node_modules/micromark": { - "version": "4.0.0", - "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "node_modules/is-array-buffer": { + "version": "3.0.5", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } + "license": "MIT" }, - "node_modules/micromark-extension-gfm": { - "version": "2.0.0", - "integrity": "sha512-yYPlZ48Ss8fRFSmlQP/QXt3/M6tEvawEVFO+jDPnFA3mGeVgzIyaeHgrIV/9AMFAjQhctKA47Bk8xBhcuaL74Q==", + "node_modules/is-async-function": { + "version": "2.1.1", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", "dependencies": { - "micromark-extension-gfm-autolink-literal": "^1.0.0", - "micromark-extension-gfm-footnote": "^1.0.0", - "micromark-extension-gfm-strikethrough": "^1.0.0", - "micromark-extension-gfm-table": "^1.0.0", - "micromark-extension-gfm-tagfilter": "^1.0.0", - "micromark-extension-gfm-task-list-item": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-types": "^1.0.0" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "1.0.5", - "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", + "node_modules/is-bigint": { + "version": "1.1.0", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "1.2.0", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "node_modules/is-boolean-object": { + "version": "1.2.2", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-encode": { - "version": "1.1.0", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "node_modules/is-callable": { + "version": "1.2.7", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "node_modules/is-core-module": { + "version": "2.16.1", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-types": { - "version": "1.1.0", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "1.1.2", - "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", + "node_modules/is-data-view": { + "version": "1.0.2", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { - "micromark-core-commonmark": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-core-commonmark": { + "node_modules/is-date-object": { "version": "1.1.0", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-map": { + "version": "2.0.3", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jose": { + "version": "6.2.8", + "integrity": "sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-typed": { + "version": "8.0.2", + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/long": { + "version": "5.3.2", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/loupe": { + "version": "3.2.1", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lowlight": { + "version": "3.3.0", + "integrity": "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "highlight.js": "~11.11.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/lzma-native": { + "version": "8.0.6", + "integrity": "sha512-09xfg67mkL2Lz20PrrDeNYZxzeW7ADtpYFbwSQh9U8+76RIzx5QsJBMy8qikv3hbUPfpy6hqwxt6FcGK81g9AA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^3.1.0", + "node-gyp-build": "^4.2.1", + "readable-stream": "^3.6.0" + }, + "bin": { + "lzmajs": "bin/lzmajs" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/lzma-native/node_modules/node-addon-api": { + "version": "3.2.1", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/matcher": { + "version": "3.0.0", + "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", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/micromark": { + "version": "4.0.0", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "2.0.0", + "integrity": "sha512-yYPlZ48Ss8fRFSmlQP/QXt3/M6tEvawEVFO+jDPnFA3mGeVgzIyaeHgrIV/9AMFAjQhctKA47Bk8xBhcuaL74Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^1.0.0", + "micromark-extension-gfm-footnote": "^1.0.0", + "micromark-extension-gfm-strikethrough": "^1.0.0", + "micromark-extension-gfm-table": "^1.0.0", + "micromark-extension-gfm-tagfilter": "^1.0.0", + "micromark-extension-gfm-task-list-item": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "1.0.5", + "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "1.2.0", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-encode": { + "version": "1.1.0", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-types": { + "version": "1.1.0", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "1.1.2", + "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-core-commonmark": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-core-commonmark": { + "version": "1.1.0", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" } }, "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-destination": { "version": "1.1.0", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-label": { + "version": "1.1.0", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "1.1.0", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-title": { + "version": "1.1.0", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-whitespace": { + "version": "1.1.0", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "1.2.0", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-chunked": { + "version": "1.1.0", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-classify-character": { + "version": "1.1.0", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-encode": { + "version": "1.1.0", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-html-tag-name": { + "version": "1.2.0", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-normalize-identifier": { + "version": "1.1.0", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-resolve-all": { + "version": "1.1.0", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-subtokenize": { + "version": "1.1.0", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-types": { + "version": "1.1.0", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "1.0.7", + "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-character": { + "version": "1.2.0", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-chunked": { + "version": "1.1.0", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-classify-character": { + "version": "1.1.0", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-resolve-all": { + "version": "1.1.0", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-types": { + "version": "1.1.0", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-table": { + "version": "1.0.7", + "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "1.1.0", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "1.2.0", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-types": { + "version": "1.1.0", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "1.0.2", + "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter/node_modules/micromark-util-types": { + "version": "1.1.0", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "1.0.5", + "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "1.1.0", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "1.2.0", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-types": { + "version": "1.1.0", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm/node_modules/micromark-util-chunked": { + "version": "1.1.0", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-extension-gfm/node_modules/micromark-util-combine-extensions": { + "version": "1.1.0", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", "dev": true, "funding": [ { @@ -5189,14 +7431,45 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", + "micromark-util-chunked": "^1.0.0", "micromark-util-types": "^1.0.0" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-label": { + "node_modules/micromark-extension-gfm/node_modules/micromark-util-symbol": { "version": "1.1.0", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm/node_modules/micromark-util-types": { + "version": "1.1.0", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", "dev": true, "funding": [ { @@ -5210,15 +7483,14 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { - "version": "1.1.0", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", "dev": true, "funding": [ { @@ -5232,13 +7504,194 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-title": { - "version": "1.1.0", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", "dev": true, "funding": [ { @@ -5250,17 +7703,11 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-whitespace": { - "version": "1.1.0", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", "dev": true, "funding": [ { @@ -5274,15 +7721,12 @@ ], "license": "MIT", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { - "version": "1.2.0", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", "dev": true, "funding": [ { @@ -5296,13 +7740,12 @@ ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-chunked": { - "version": "1.1.0", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "dev": true, "funding": [ { @@ -5316,12 +7759,14 @@ ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", "dev": true, "funding": [ { @@ -5335,14 +7780,15 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-encode": { - "version": "1.1.0", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "dev": true, "funding": [ { @@ -5356,9 +7802,9 @@ ], "license": "MIT" }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", + "node_modules/micromark-util-types": { + "version": "2.0.2", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "dev": true, "funding": [ { @@ -5372,2067 +7818,2269 @@ ], "license": "MIT" }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "node_modules/mime-db": { + "version": "1.54.0", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/minizlib": { + "version": "2.1.2", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "micromark-util-symbol": "^1.0.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "micromark-util-types": "^1.0.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "ISC" + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-subtokenize": { - "version": "1.1.0", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "ISC" }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-types": { - "version": "1.1.0", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "node_modules/minizlib": { + "version": "3.1.0", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "1.0.7", - "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", + "node_modules/mkdirp": { + "version": "1.0.4", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "bin": { + "mkdirp": "bin/cmd.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=10" } }, - "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-character": { + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/mri": { "version": "1.2.0", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "engines": { + "node": ">=4" } }, - "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-chunked": { - "version": "1.1.0", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "node_modules/ms": { + "version": "2.1.3", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^1.0.0" + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "node_modules/napi-build-utils": { + "version": "2.0.0", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "node_modules/nice-try": { + "version": "1.0.5", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.88.0", + "integrity": "sha512-At6b4UqIEVudaqPsXjmUO1r/N5BUr4yhDGs5PkBE8/oG5+TfLPhFechiskFsnT6Ql0VfUXbalUUCbfXxtj7K+w==", "license": "MIT", "dependencies": { - "micromark-util-types": "^1.0.0" + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" } }, - "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "node_modules/node-api-version": { + "version": "0.1.4", + "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + } }, - "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-types": { - "version": "1.1.0", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "node_modules/node-domexception": { + "version": "1.0.0", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, "funding": [ { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" }, { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://paypal.me/jimmywarting" } ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } }, - "node_modules/micromark-extension-gfm-table": { - "version": "1.0.7", - "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", + "node_modules/node-fetch": { + "version": "3.3.2", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dev": true, "license": "MIT", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { - "version": "1.1.0", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "node_modules/node-gyp": { + "version": "9.4.1", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" } }, - "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { - "version": "1.2.0", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "node_modules/node-gyp-build": { + "version": "4.8.4", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, - "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "node_modules/node-gyp/node_modules/chownr": { + "version": "2.0.0", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "ISC", + "engines": { + "node": ">=10" + } }, - "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-types": { - "version": "1.1.0", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "node_modules/node-gyp/node_modules/minipass": { + "version": "5.0.0", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "ISC", + "engines": { + "node": ">=8" + } }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "1.0.2", - "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", + "node_modules/node-gyp/node_modules/minizlib": { + "version": "2.1.2", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "license": "MIT", "dependencies": { - "micromark-util-types": "^1.0.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 8" } }, - "node_modules/micromark-extension-gfm-tagfilter/node_modules/micromark-util-types": { - "version": "1.1.0", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "node_modules/node-gyp/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "1.0.5", - "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", + "node_modules/node-gyp/node_modules/tar": { + "version": "6.2.1", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "2.0.2", + "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/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, + "license": "ISC" + }, + "node_modules/node-notifier": { + "version": "10.0.1", + "integrity": "sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==", "license": "MIT", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "growly": "^1.3.0", + "is-wsl": "^2.2.0", + "semver": "^7.3.5", + "shellwords": "^0.1.1", + "uuid": "^8.3.2", + "which": "^2.0.2" + } + }, + "node_modules/node-notifier/node_modules/uuid": { + "version": "8.3.2", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/node-notifier/node_modules/which": { + "version": "2.0.2", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { - "version": "1.1.0", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "node_modules/nopt": { + "version": "6.0.0", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { - "version": "1.2.0", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "node_modules/normalize-package-data": { + "version": "2.5.0", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "ISC", + "bin": { + "semver": "bin/semver" + } }, - "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-types": { - "version": "1.1.0", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "node_modules/normalize-url": { + "version": "6.1.0", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/micromark-extension-gfm/node_modules/micromark-util-chunked": { - "version": "1.1.0", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "node_modules/npm-run-all": { + "version": "4.1.5", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^1.0.0" + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" } }, - "node_modules/micromark-extension-gfm/node_modules/micromark-util-combine-extensions": { - "version": "1.1.0", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/micromark-extension-gfm/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } }, - "node_modules/micromark-extension-gfm/node_modules/micromark-util-types": { - "version": "1.1.0", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT" }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.6", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" } }, - "node_modules/micromark-factory-label": { + "node_modules/npm-run-all/node_modules/path-key": { "version": "2.0.1", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "node_modules/npmlog": { + "version": "6.0.2", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "node_modules/object-assign": { + "version": "4.1.1", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "node_modules/object-inspect": { + "version": "1.13.4", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "node_modules/object-keys": { + "version": "1.1.1", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "node_modules/object.assign": { + "version": "4.1.7", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "node_modules/on-finished": { + "version": "2.4.1", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0" + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "node_modules/once": { + "version": "1.4.0", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openai": { + "version": "6.26.0", + "integrity": "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" + "zod": { + "optional": true } - ], - "license": "MIT" + } }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "node_modules/own-keys": { + "version": "1.0.1", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "node_modules/p-cancelable": { + "version": "2.1.1", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "node_modules/p-map": { + "version": "4.0.0", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-types": "^2.0.0" + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "node_modules/p-retry": { + "version": "4.6.2", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "4.0.0", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" } }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "node_modules/parseurl": { + "version": "1.3.3", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "node_modules/partial-json": { + "version": "0.1.7", + "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT" }, - "node_modules/mime-db": { - "version": "1.54.0", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/mime-types": { - "version": "3.0.2", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "node_modules/path-key": { + "version": "3.1.1", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "mime-db": "^1.54.0" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=18" + "node": ">=16 || 14 >=14.18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "ISC" }, - "node_modules/mimic-response": { - "version": "3.1.0", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "node_modules/path-to-regexp": { + "version": "8.3.0", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=10" - }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/minimatch": { - "version": "3.1.5", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/path-type": { + "version": "3.0.0", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "pify": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/minimist": { - "version": "1.2.8", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/pathe": { + "version": "2.0.3", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 14.16" } }, - "node_modules/minipass": { - "version": "7.1.3", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "node_modules/pend": { + "version": "1.2.0", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "node_modules/pidtree": { + "version": "0.3.1", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">= 8" + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/pkce-challenge": { + "version": "5.0.1", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=16.20.0" } }, - "node_modules/minipass-collect/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "node_modules/postcss": { + "version": "8.5.26", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "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": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" + "node": "^10 || ^12 || >=14" } }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", + "node_modules/prebuild-install": { + "version": "7.1.3", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/minipass-fetch/node_modules/minizlib": { - "version": "2.1.2", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/preprocess": { + "version": "3.2.0", + "integrity": "sha512-cO+Rf+Ose/eD+ze8Hxd9p9nS1xT8thYqv8owG/V8+IS/Remd7Z17SvaRK/oJxp08yaM8zb+QTckDKJUul2pk7g==", "dev": true, - "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "xregexp": "3.1.0" }, "engines": { - "node": ">= 8" + "node": ">= 0.10.0" } }, - "node_modules/minipass-fetch/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "node_modules/proc-log": { + "version": "5.0.0", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, "engines": { - "node": ">= 8" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/progress": { + "version": "2.0.3", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/promise-inflight": { + "version": "1.0.1", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true, "license": "ISC" }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "node_modules/promise-retry": { + "version": "2.0.1", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "err-code": "^2.0.2", + "retry": "^0.12.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/promise-retry/node_modules/retry": { + "version": "0.12.0", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/property-information": { + "version": "7.2.0", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", "dev": true, - "license": "ISC" + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "node_modules/protobufjs": { + "version": "7.6.5", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", "dev": true, - "license": "ISC", + "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { - "minipass": "^3.0.0" + "@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": ">=8" + "node": ">=12.0.0" } }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/proxy-addr": { + "version": "2.0.7", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/minipass-sized/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minizlib": { - "version": "3.1.0", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "dev": true, + "node_modules/pump": { + "version": "3.0.4", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "license": "MIT", "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/qs": { + "version": "6.15.0", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" - }, - "node_modules/mri": { - "version": "1.2.0", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "node_modules/quick-lru": { + "version": "5.1.1", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ms": { - "version": "2.1.3", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "1.0.0", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "node_modules/range-parser": { + "version": "1.2.1", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/nice-try": { - "version": "1.0.5", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "node_modules/raw-body": { + "version": "3.0.2", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "dev": true, - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.88.0", - "integrity": "sha512-At6b4UqIEVudaqPsXjmUO1r/N5BUr4yhDGs5PkBE8/oG5+TfLPhFechiskFsnT6Ql0VfUXbalUUCbfXxtj7K+w==", "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.10" } }, - "node_modules/node-api-version": { - "version": "0.1.4", - "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.3", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/node-gyp": { - "version": "9.4.1", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "license": "MIT", + "node_modules/rc": { + "version": "1.2.8", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" + "rc": "cli.js" } }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "node_modules/read-binary-file-arch": { + "version": "1.0.6", + "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", "dev": true, "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" + "read-binary-file-arch": "cli.js" } }, - "node_modules/node-gyp/node_modules/chownr": { - "version": "2.0.0", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "node_modules/read-pkg": { + "version": "3.0.0", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/node-gyp/node_modules/minipass": { - "version": "5.0.0", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", + "node_modules/readable-stream": { + "version": "3.6.2", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/node-gyp/node_modules/minizlib": { - "version": "2.1.2", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-gyp/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-gyp/node_modules/tar": { - "version": "6.2.1", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "node_modules/require-directory": { + "version": "2.1.1", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/node-gyp/node_modules/which": { + "node_modules/require-from-string": { "version": "2.0.2", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "license": "ISC", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { - "node-which": "bin/node-which" + "resolve": "bin/resolve" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-gyp/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/resolve-alpn": { + "version": "1.2.1", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/node-notifier": { - "version": "10.0.1", - "integrity": "sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==", + "node_modules/responselike": { + "version": "2.0.1", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, "license": "MIT", "dependencies": { - "growly": "^1.3.0", - "is-wsl": "^2.2.0", - "semver": "^7.3.5", - "shellwords": "^0.1.1", - "uuid": "^8.3.2", - "which": "^2.0.2" + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-notifier/node_modules/uuid": { - "version": "8.3.2", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "node_modules/retry": { + "version": "0.13.1", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">= 4" } }, - "node_modules/node-notifier/node_modules/which": { - "version": "2.0.2", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/rimraf": { + "version": "3.0.2", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "glob": "^7.1.3" }, "bin": { - "node-which": "bin/node-which" + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "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" + "node": ">=8.0" } }, - "node_modules/nopt": { - "version": "6.0.0", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "node_modules/roarr/node_modules/sprintf-js": { + "version": "1.1.3", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/rollup": { + "version": "4.62.4", + "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==", + "dev": true, + "license": "MIT", "dependencies": { - "abbrev": "^1.0.0" + "@types/estree": "1.0.9" }, "bin": { - "nopt": "bin/nopt.js" + "rollup": "dist/bin/rollup" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.4", + "@rollup/rollup-android-arm64": "4.62.4", + "@rollup/rollup-darwin-arm64": "4.62.4", + "@rollup/rollup-darwin-x64": "4.62.4", + "@rollup/rollup-freebsd-arm64": "4.62.4", + "@rollup/rollup-freebsd-x64": "4.62.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.4", + "@rollup/rollup-linux-arm-musleabihf": "4.62.4", + "@rollup/rollup-linux-arm64-gnu": "4.62.4", + "@rollup/rollup-linux-arm64-musl": "4.62.4", + "@rollup/rollup-linux-loong64-gnu": "4.62.4", + "@rollup/rollup-linux-loong64-musl": "4.62.4", + "@rollup/rollup-linux-ppc64-gnu": "4.62.4", + "@rollup/rollup-linux-ppc64-musl": "4.62.4", + "@rollup/rollup-linux-riscv64-gnu": "4.62.4", + "@rollup/rollup-linux-riscv64-musl": "4.62.4", + "@rollup/rollup-linux-s390x-gnu": "4.62.4", + "@rollup/rollup-linux-x64-gnu": "4.62.4", + "@rollup/rollup-linux-x64-musl": "4.62.4", + "@rollup/rollup-openbsd-x64": "4.62.4", + "@rollup/rollup-openharmony-arm64": "4.62.4", + "@rollup/rollup-win32-arm64-msvc": "4.62.4", + "@rollup/rollup-win32-ia32-msvc": "4.62.4", + "@rollup/rollup-win32-x64-gnu": "4.62.4", + "@rollup/rollup-win32-x64-msvc": "4.62.4", + "fsevents": "~2.3.2" } }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/router": { + "version": "2.2.0", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "node_modules/sade": { + "version": "1.8.1", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "mri": "^1.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, - "node_modules/npm-run-all": { - "version": "4.1.5", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "node_modules/safe-array-concat": { + "version": "1.1.3", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">= 4" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/ansi-styles": { - "version": "3.2.1", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/color-convert": { - "version": "1.9.3", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/safe-regex-test": { + "version": "1.1.0", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/color-name": { - "version": "1.1.3", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, - "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.6", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "node_modules/section-matter": { + "version": "1.0.0", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", "dev": true, "license": "MIT", "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/npm-run-all/node_modules/path-key": { - "version": "2.0.1", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/npm-run-all/node_modules/semver": { - "version": "5.7.2", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, + "node_modules/semver": { + "version": "7.7.4", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { - "semver": "bin/semver" - } - }, - "node_modules/npm-run-all/node_modules/shebang-command": { - "version": "1.2.0", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/npm-run-all/node_modules/shebang-regex": { + "node_modules/semver-compare": { "version": "1.0.0", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "optional": true }, - "node_modules/npmlog": { - "version": "6.0.2", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", + "node_modules/send": { + "version": "1.2.1", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/serialize-error": { + "version": "7.0.1", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-inspect": { - "version": "1.13.4", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "node_modules/serve-static": { + "version": "2.2.1", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "dev": true, "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, "engines": { - "node": ">= 0.4" + "node": ">= 18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/set-blocking": { + "version": "2.0.0", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, "engines": { "node": ">= 0.4" } }, - "node_modules/object.assign": { - "version": "4.1.7", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "node_modules/set-function-name": { + "version": "2.0.2", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/on-finished": { - "version": "2.4.1", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/set-proto": { + "version": "1.0.0", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "license": "MIT", "dependencies": { - "ee-first": "1.1.1" + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" + "node": ">= 0.4" } }, - "node_modules/openai": { - "version": "6.17.0", - "integrity": "sha512-NHRpPEUPzAvFOAFs9+9pC6+HCw/iWsYsKCMPXH5Kw7BpMxqd8g/A07/1o7Gx2TWtCnzevVRyKMRFqyiHyAlqcA==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true, - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } + "license": "ISC" }, - "node_modules/own-keys": { - "version": "1.0.1", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "node_modules/shebang-command": { + "version": "2.0.0", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/p-map": { - "version": "4.0.0", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/shell-quote": { + "version": "1.8.3", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" + "node_modules/shellwords": { + "version": "0.1.1", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "license": "MIT" }, - "node_modules/parse-json": { - "version": "4.0.0", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "node_modules/side-channel": { + "version": "1.1.0", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/side-channel-list": { + "version": "1.0.0", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/partial-json": { - "version": "0.1.7", - "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-is-absolute": { + "node_modules/side-channel-map": { "version": "1.0.1", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-key": { - "version": "3.1.1", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "node_modules/siginfo": { + "version": "2.0.0", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, - "node_modules/path-to-regexp": { - "version": "8.3.0", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "node_modules/signal-exit": { + "version": "3.0.7", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "node_modules/path-type": { - "version": "3.0.0", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "node_modules/smart-buffer": { + "version": "4.2.0", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "license": "MIT", - "dependencies": { - "pify": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/pend": { - "version": "1.2.0", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/socks": { + "version": "2.8.7", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/pidtree": { - "version": "0.3.1", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" }, "engines": { - "node": ">=0.10" + "node": ">= 10" } }, - "node_modules/pify": { - "version": "3.0.0", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/source-map-js": { + "version": "1.2.1", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/pkce-challenge": { - "version": "5.0.1", - "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=16.20.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "node_modules/spdx-correct": { + "version": "3.2.0", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", - "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "license": "MIT", "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/preprocess": { - "version": "3.2.0", - "integrity": "sha512-cO+Rf+Ose/eD+ze8Hxd9p9nS1xT8thYqv8owG/V8+IS/Remd7Z17SvaRK/oJxp08yaM8zb+QTckDKJUul2pk7g==", + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, - "dependencies": { - "xregexp": "3.1.0" - }, - "engines": { - "node": ">= 0.10.0" + "license": "CC0-1.0" + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sqlite-vec": { + "version": "0.1.7-alpha.2", + "integrity": "sha512-rNgRCv+4V4Ed3yc33Qr+nNmjhtrMnnHzXfLVPeGb28Dx5mmDL3Ngw/Wk8vhCGjj76+oC6gnkmMG8y73BZWGBwQ==", + "license": "MIT OR Apache", + "optionalDependencies": { + "sqlite-vec-darwin-arm64": "0.1.7-alpha.2", + "sqlite-vec-darwin-x64": "0.1.7-alpha.2", + "sqlite-vec-linux-arm64": "0.1.7-alpha.2", + "sqlite-vec-linux-x64": "0.1.7-alpha.2", + "sqlite-vec-windows-x64": "0.1.7-alpha.2" } }, - "node_modules/proc-log": { - "version": "5.0.0", - "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "node_modules/sqlite-vec-darwin-arm64": { + "version": "0.1.7-alpha.2", + "integrity": "sha512-raIATOqFYkeCHhb/t3r7W7Cf2lVYdf4J3ogJ6GFc8PQEgHCPEsi+bYnm2JT84MzLfTlSTIdxr4/NKv+zF7oLPw==", + "cpu": [ + "arm64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/sqlite-vec-darwin-x64": { + "version": "0.1.7-alpha.2", + "integrity": "sha512-jeZEELsQjjRsVojsvU5iKxOvkaVuE+JYC8Y4Ma8U45aAERrDYmqZoHvgSG7cg1PXL3bMlumFTAmHynf1y4pOzA==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/sqlite-vec-linux-arm64": { + "version": "0.1.7-alpha.2", + "integrity": "sha512-6Spj4Nfi7tG13jsUG+W7jnT0bCTWbyPImu2M8nWp20fNrd1SZ4g3CSlDAK8GBdavX7wRlbBHCZ+BDa++rbDewA==", + "cpu": [ + "arm64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/sqlite-vec-linux-x64": { + "version": "0.1.7-alpha.2", + "integrity": "sha512-IcgrbHaDccTVhXDf8Orwdc2+hgDLAFORl6OBUhcvlmwswwBP1hqBTSEhovClG4NItwTOBNgpwOoQ7Qp3VDPWLg==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/sqlite-vec-windows-x64": { + "version": "0.1.7-alpha.2", + "integrity": "sha512-TRP6hTjAcwvQ6xpCZvjP00pdlda8J38ArFy1lMYhtQWXiIBmWnhMaMbq4kaeCYwvTTddfidatRS+TJrwIKB/oQ==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/ssri": { + "version": "9.0.1", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/progress": { - "version": "2.0.3", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "node_modules/ssri/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, - "node_modules/promise-retry": { - "version": "2.0.1", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "node_modules/stackback": { + "version": "0.0.2", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "node_modules/promise-retry/node_modules/retry": { - "version": "0.12.0", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "node_modules/statuses": { + "version": "2.0.2", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">= 0.8" } }, - "node_modules/property-information": { - "version": "7.2.0", - "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "node_modules/std-env": { + "version": "3.10.0", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "license": "MIT" }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, "license": "MIT", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" } }, - "node_modules/pump": { - "version": "3.0.4", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "node_modules/string_decoder": { + "version": "1.3.0", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "safe-buffer": "~5.2.0" } }, - "node_modules/qs": { - "version": "6.15.0", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "side-channel": "^1.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/quick-lru": { - "version": "5.1.1", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/raw-body": { - "version": "3.0.2", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.3", - "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/read-binary-file-arch": { - "version": "1.0.6", - "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "bin": { - "read-binary-file-arch": "cli.js" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/read-pkg": { - "version": "3.0.0", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=4" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "node": ">= 0.4" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -7441,18 +10089,15 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -7461,274 +10106,281 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/stringify-entities": { + "version": "4.0.4", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/strip-ansi": { + "version": "7.2.0", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/resolve": { - "version": "1.22.11", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/responselike": { + "node_modules/strip-json-comments": { "version": "2.0.1", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-literal": { + "version": "3.1.0", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", "dev": true, "license": "MIT", "dependencies": { - "lowercase-keys": "^2.0.0" + "js-tokens": "^9.0.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/sumchecker": { + "version": "3.0.1", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "debug": "^4.1.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">= 8.0" } }, - "node_modules/roarr": { - "version": "2.15.4", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "node_modules/supports-color": { + "version": "7.2.0", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "BSD-3-Clause", - "optional": true, + "license": "MIT", "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" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8.0" + "node": ">=8" } }, - "node_modules/roarr/node_modules/sprintf-js": { - "version": "1.1.3", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "license": "BSD-3-Clause", - "optional": true + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/router": { - "version": "2.2.0", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "node_modules/tar": { + "version": "7.5.11", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/sade": { - "version": "1.8.1", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, + "node_modules/tar-fs": { + "version": "2.1.4", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" } }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dev": true, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/tinybench": { + "version": "2.9.0", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, "license": "MIT" }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "node_modules/tinyexec": { + "version": "0.3.2", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">= 0.4" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "node_modules/tinypool": { + "version": "1.1.1", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/tinyrainbow": { + "version": "2.0.0", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/section-matter": { - "version": "1.0.0", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "node_modules/tinyspy": { + "version": "4.0.4", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, "license": "MIT", - "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" - }, "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/semver": { - "version": "7.7.4", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/toidentifier": { + "version": "1.0.1", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.6" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "node_modules/trim-lines": { + "version": "3.0.1", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "dev": true, "license": "MIT", - "optional": true + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/send": { - "version": "1.2.1", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "node_modules/ts-algebra": { + "version": "2.0.0", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" + "safe-buffer": "^5.0.1" }, "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": "*" } }, - "node_modules/serialize-error": { - "version": "7.0.1", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "node_modules/type-fest": { + "version": "0.13.1", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, - "license": "MIT", + "license": "(MIT OR CC0-1.0)", "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, "engines": { "node": ">=10" }, @@ -7736,109 +10388,124 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serve-static": { - "version": "2.2.1", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "node_modules/type-is": { + "version": "2.0.1", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.6" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "node_modules/typebox": { + "version": "1.1.38", + "integrity": "sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/set-function-length": { - "version": "1.2.2", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/set-proto": { - "version": "1.0.0", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/typescript": { + "version": "5.9.3", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=8" + "node": ">=14.17" } }, - "node_modules/shell-quote": { - "version": "1.8.3", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "node_modules/unbox-primitive": { + "version": "1.1.0", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, "engines": { "node": ">= 0.4" }, @@ -7846,1013 +10513,1394 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shellwords": { - "version": "0.1.1", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "node_modules/undici-types": { + "version": "5.26.5", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, "license": "MIT" }, - "node_modules/side-channel": { - "version": "1.1.0", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "node_modules/unique-filename": { + "version": "2.0.1", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" + "unique-slug": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/unique-slug": { + "version": "3.0.0", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "imurmurhash": "^0.1.4" }, "engines": { - "node": ">= 0.4" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "node_modules/unist-util-position": { + "version": "5.0.0", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/unist-util-visit": { + "version": "5.1.0", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "dev": true, - "license": "ISC" - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/simple-get": { - "version": "4.0.1", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, "license": "MIT", "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "node_modules/universalify": { + "version": "2.0.1", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">= 10.0.0" } }, - "node_modules/socks": { - "version": "2.8.7", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "node_modules/unpipe": { + "version": "1.0.0", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "node": ">= 0.8" } }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "node_modules/util-deprecate": { + "version": "1.0.2", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "9.0.1", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/uvu": { + "version": "0.5.6", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" + }, + "bin": { + "uvu": "bin.js" }, "engines": { - "node": ">= 10" + "node": ">=8" } }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "node_modules/uvu/node_modules/diff": { + "version": "5.2.2", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "license": "Apache-2.0", "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "node_modules/vary": { + "version": "1.1.2", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, - "license": "CC-BY-3.0" + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/vfile": { + "version": "6.0.3", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "dev": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.23", - "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "node_modules/vfile-message": { + "version": "4.0.3", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "dev": true, - "license": "CC0-1.0" + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "node_modules/vite-node": { + "version": "3.2.4", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/sqlite-vec": { - "version": "0.1.7-alpha.2", - "integrity": "sha512-rNgRCv+4V4Ed3yc33Qr+nNmjhtrMnnHzXfLVPeGb28Dx5mmDL3Ngw/Wk8vhCGjj76+oC6gnkmMG8y73BZWGBwQ==", - "license": "MIT OR Apache", - "optionalDependencies": { - "sqlite-vec-darwin-arm64": "0.1.7-alpha.2", - "sqlite-vec-darwin-x64": "0.1.7-alpha.2", - "sqlite-vec-linux-arm64": "0.1.7-alpha.2", - "sqlite-vec-linux-x64": "0.1.7-alpha.2", - "sqlite-vec-windows-x64": "0.1.7-alpha.2" + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/sqlite-vec-darwin-arm64": { - "version": "0.1.7-alpha.2", - "integrity": "sha512-raIATOqFYkeCHhb/t3r7W7Cf2lVYdf4J3ogJ6GFc8PQEgHCPEsi+bYnm2JT84MzLfTlSTIdxr4/NKv+zF7oLPw==", - "cpu": [ - "arm64" - ], - "license": "MIT OR Apache", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/sqlite-vec-darwin-x64": { - "version": "0.1.7-alpha.2", - "integrity": "sha512-jeZEELsQjjRsVojsvU5iKxOvkaVuE+JYC8Y4Ma8U45aAERrDYmqZoHvgSG7cg1PXL3bMlumFTAmHynf1y4pOzA==", + "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ - "x64" + "ppc64" ], - "license": "MIT OR Apache", + "dev": true, + "license": "MIT", "optional": true, "os": [ - "darwin" - ] - }, - "node_modules/sqlite-vec-linux-arm64": { - "version": "0.1.7-alpha.2", - "integrity": "sha512-6Spj4Nfi7tG13jsUG+W7jnT0bCTWbyPImu2M8nWp20fNrd1SZ4g3CSlDAK8GBdavX7wRlbBHCZ+BDa++rbDewA==", - "cpu": [ - "arm64" + "aix" ], - "license": "MIT OR Apache", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">=18" + } }, - "node_modules/sqlite-vec-linux-x64": { - "version": "0.1.7-alpha.2", - "integrity": "sha512-IcgrbHaDccTVhXDf8Orwdc2+hgDLAFORl6OBUhcvlmwswwBP1hqBTSEhovClG4NItwTOBNgpwOoQ7Qp3VDPWLg==", + "node_modules/vite-node/node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ - "x64" + "arm" ], - "license": "MIT OR Apache", + "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" - ] - }, - "node_modules/sqlite-vec-windows-x64": { - "version": "0.1.7-alpha.2", - "integrity": "sha512-TRP6hTjAcwvQ6xpCZvjP00pdlda8J38ArFy1lMYhtQWXiIBmWnhMaMbq4kaeCYwvTTddfidatRS+TJrwIKB/oQ==", - "cpu": [ - "x64" + "android" ], - "license": "MIT OR Apache", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/ssri": { - "version": "9.0.1", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/ssri/node_modules/minipass": { - "version": "3.3.6", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/vite-node/node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/ssri/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/statuses": { - "version": "2.0.2", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/vite-node/node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 0.8" + "node": ">=18" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/vite-node/node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/vite-node/node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/vite-node/node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/string.prototype.padend": { - "version": "3.1.6", - "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", + "node_modules/vite-node/node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "node_modules/vite-node/node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/strip-ansi": { - "version": "7.2.0", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "node_modules/vite-node/node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/vite-node/node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + }, + "node_modules/vite-node/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "node_modules/vite-node/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/sumchecker": { - "version": "3.0.1", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "node_modules/vite-node/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.1.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">= 8.0" + "node": ">=18" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/vite-node/node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/vite-node/node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/tar": { - "version": "7.5.11", - "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", + "node_modules/vite-node/node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=18" } }, - "node_modules/tar-fs": { - "version": "2.1.4", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "node_modules/vite-node/node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/vite-node/node_modules/esbuild": { + "version": "0.28.2", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/vite-node/node_modules/vite": { + "version": "7.3.6", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "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", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.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 + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "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/tinyglobby": { - "version": "0.2.15", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "node_modules/vitest": { + "version": "3.2.7", + "integrity": "sha512-KrxIJ62Fd89gfysR4WotlgZABiz2dqFPgqGzX7s+CwsqLFomRH7777ZcrOD6+WVAh7khPQP41A+BKbpcJFrdEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.7", + "@vitest/mocker": "3.2.7", + "@vitest/pretty-format": "^3.2.7", + "@vitest/runner": "3.2.7", + "@vitest/snapshot": "3.2.7", + "@vitest/spy": "3.2.7", + "@vitest/utils": "3.2.7", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" }, "engines": { - "node": ">=12.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.7", + "@vitest/ui": "3.2.7", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=0.6" + "node": ">=18" } }, - "node_modules/trim-lines": { - "version": "3.0.1", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "node_modules/vitest/node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, + "node_modules/vitest/node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/type-fest": { - "version": "0.13.1", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "node_modules/vitest/node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/type-is": { - "version": "2.0.1", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.6" + "node": ">=18" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "node_modules/vitest/node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "node_modules/vitest/node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/typescript": { - "version": "5.9.3", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "node_modules/vitest/node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14.17" + "node": ">=18" } }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "node_modules/vitest/node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "node_modules/vitest/node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/unique-filename": { - "version": "2.0.1", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/unique-slug": { - "version": "3.0.0", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/unist-util-is": { - "version": "6.0.1", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "node_modules/vitest/node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/vitest/node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/unist-util-visit": { - "version": "5.1.0", - "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "node_modules/vitest/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/universalify": { - "version": "2.0.1", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/vitest/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 10.0.0" + "node": ">=18" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 0.8" + "node": ">=18" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/uuid": { - "version": "9.0.1", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" + "node_modules/vitest/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" ], + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, - "node_modules/uvu": { - "version": "0.5.6", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "node_modules/vitest/node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/uvu/node_modules/diff": { - "version": "5.2.2", - "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "node_modules/vitest/node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.3.1" + "node": ">=18" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/vitest/node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/vary": { - "version": "1.1.2", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/vitest/node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.8" + "node": ">=18" } }, - "node_modules/vfile": { - "version": "6.0.3", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "3.2.7", + "integrity": "sha512-Trr0hYO9CM3Wj6ksWHRhK9IZpIY6wTMO5u/MqXurMxT57sWBaOPEtP3Oq60ihZuh5JsiagKfz95OcxdEP6dBrA==", "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "@vitest/spy": "3.2.7", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/vfile-message": { - "version": "4.0.3", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "node_modules/vitest/node_modules/esbuild": { + "version": "0.28.2", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "7.3.6", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.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 + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "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/wcwidth": { @@ -8864,6 +11912,15 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/web-tree-sitter": { "version": "0.22.6", "integrity": "sha512-hS87TH71Zd6mGAmYCvlgxeGDjqd9GTeqXNqTT+u0Gs51uIozNIaaq/kUAbV/Zf56jb2ZOyG8BxZs2GG9wbLi6Q==", @@ -8966,6 +12023,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wide-align": { "version": "1.1.5", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", @@ -9177,6 +12250,27 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/ws": { + "version": "8.21.3", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xregexp": { "version": "3.1.0", "integrity": "sha512-4Y1x6DyB8xRoxosooa6PlGWqmmSKatbzhrftZ7Purmm4B8R4qIEJG1A2hZsdz5DhmIqS0msC0I7KEq93GphEVg==", diff --git a/package.json b/package.json index f10cf0f..6b91a20 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,18 @@ "category": "Mutsumi", "icon": "$(server-environment)" }, + { + "command": "mutsumi.manageProviders", + "title": "%command.manageProviders.title%", + "category": "Mutsumi", + "icon": "$(key)" + }, + { + "command": "mutsumi.migrateProviderCredentials", + "title": "%command.migrateProviderCredentials.title%", + "category": "Mutsumi", + "icon": "$(shield)" + }, { "command": "mutsumi.renameSession", "title": "%command.renameSession.title%", @@ -400,6 +412,7 @@ "properties": { "mutsumi.providers": { "type": "array", + "deprecationMessage": "Deprecated: use Mutsumi: Manage Model Providers. API keys are now stored in VS Code SecretStorage.", "markdownDescription": "%configuration.providers.markdownDescription%", "items": { "type": "object", @@ -428,6 +441,7 @@ }, "mutsumi.models": { "type": "object", + "deprecationMessage": "Deprecated: built-in catalogs and custom provider model discovery replace this setting.", "markdownDescription": "%configuration.models.markdownDescription%", "additionalProperties": { "type": "array", @@ -436,6 +450,49 @@ } } }, + "mutsumi.customProviders": { + "type": "object", + "markdownDescription": "%configuration.customProviders.markdownDescription%", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "displayName": { + "type": "string" + }, + "baseUrl": { + "type": "string", + "format": "uri" + }, + "api": { + "type": "string", + "enum": [ + "openai-completions", + "openai-responses" + ], + "default": "openai-completions" + }, + "auth": { + "type": "string", + "enum": [ + "apiKey", + "none" + ], + "default": "apiKey" + }, + "models": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + } + }, + "required": [ + "baseUrl" + ] + } + }, "mutsumi.defaultModel": { "type": "object", "markdownDescription": "%configuration.defaultModel.markdownDescription%", @@ -453,7 +510,7 @@ ], "default": { "model": "kimi-for-coding", - "provider": "kimi-for-coding" + "provider": "kimi-coding" } }, "mutsumi.titleGeneratorModel": { @@ -535,24 +592,66 @@ { "type": "object", "properties": { - "type": { "const": "stdio" }, - "command": { "type": "string", "minLength": 1 }, - "args": { "type": "array", "items": { "type": "string" } }, - "cwd": { "type": "string" }, - "env": { "type": "object", "additionalProperties": { "type": ["string", "number"] } }, - "timeout": { "type": "number", "exclusiveMinimum": 0 } + "type": { + "const": "stdio" + }, + "command": { + "type": "string", + "minLength": 1 + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "cwd": { + "type": "string" + }, + "env": { + "type": "object", + "additionalProperties": { + "type": [ + "string", + "number" + ] + } + }, + "timeout": { + "type": "number", + "exclusiveMinimum": 0 + } }, - "required": ["type", "command"] + "required": [ + "type", + "command" + ] }, { "type": "object", "properties": { - "type": { "const": "http" }, - "url": { "type": "string", "format": "uri" }, - "headers": { "type": "object", "additionalProperties": { "type": "string" } }, - "timeout": { "type": "number", "exclusiveMinimum": 0 } + "type": { + "const": "http" + }, + "url": { + "type": "string", + "format": "uri" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "timeout": { + "type": "number", + "exclusiveMinimum": 0 + } }, - "required": ["type", "url"] + "required": [ + "type", + "url" + ] } ] } @@ -635,9 +734,10 @@ } }, "scripts": { + "test": "vitest run", "vscode:prepublish": "npm run package", "compile": "npm run check-types && node esbuild.js", - "check-types": "npx tsc --noEmit && npx tsc --noEmit -p tsconfig.renderer.json", + "check-types": "npx tsc --noEmit && npx tsc --noEmit -p tsconfig.renderer.json && npx tsc --noEmit -p tests/tsconfig.json", "watch": "npm-run-all -p watch:*", "watch:esbuild": "node esbuild.js --watch", "watch:tsc": "npx tsc --noEmit --watch", @@ -645,7 +745,9 @@ "package-local": "vsce package && npm install" }, "devDependencies": { + "@earendil-works/pi-ai": "^0.82.1", "@electron/rebuild": "^4.0.3", + "@modelcontextprotocol/sdk": "^1.30.0", "@types/better-sqlite3": "^7.6.13", "@types/diff": "^8.0.0", "@types/express": "^5.0.6", @@ -665,13 +767,12 @@ "lowlight": "^3.3.0", "micromark": "^4.0.0", "micromark-extension-gfm": "^2.0.0", - "@modelcontextprotocol/sdk": "^1.30.0", "npm-run-all": "^4.1.5", - "openai": "^6.17.0", "partial-json": "^0.1.7", "preprocess": "^3.2.0", "typescript": "^5.9.3", - "uuid": "^9.0.1" + "uuid": "^9.0.1", + "vitest": "^3.2.7" }, "dependencies": { "better-sqlite3": "^12.8.0", diff --git a/package.nls.json b/package.nls.json index 5ec9d4e..b580ca0 100644 --- a/package.nls.json +++ b/package.nls.json @@ -16,6 +16,8 @@ "command.rejectRequest.title": "Reject", "command.customRequestAction.title": "Inspect", "command.selectModel.title": "Select Model", + "command.manageProviders.title": "Manage Model Providers", + "command.migrateProviderCredentials.title": "Migrate Provider Credentials", "command.renameSession.title": "Rename Session", "command.debugContext.title": "Debug Context", "command.pruneGhostBlocks.title": "Prune Outdated References", @@ -39,12 +41,13 @@ "command.removeShellTask.title": "Remove", "configuration.title": "Mutsumi", - "configuration.providers.markdownDescription": "Configured LLM API providers\n\nExample:\n```json\n\"mutsumi.providers\": [\n {\n \"name\": \"kimi-for-coding\",\n \"baseurl\": \"https://api.kimi.com/coding/v1\",\n \"api_key\": \"sk-kimi-XXXXXXXXXXXXXXXXXXXXXX\"\n }\n]\n```", + "configuration.providers.markdownDescription": "**Deprecated migration-only setting.** Use **Mutsumi: Manage Model Providers**. Existing plaintext keys can be moved to VS Code SecretStorage with **Mutsumi: Migrate Legacy Provider Credentials**.", "configuration.providers.items.name.markdownDescription": "LLM API Provider Name (e.g., OpenAI, Anthropic, llama.cpp)", "configuration.providers.items.baseurl.markdownDescription": "LLM API BaseURL (e.g., https://api.openai.com/v1, http://localhost:8080/v1)", - "configuration.providers.items.api_key.markdownDescription": "LLM API Key (required, use dummy value for local deployments without authentication)", - "configuration.models.markdownDescription": "Provider to models mapping. Key is the provider name from `mutsumi.providers`, value is an array of model identifiers supported by that provider. **Edit this in `settings.json` directly.**\n\nExample:\n```json\n\"mutsumi.models\": {\n \"Baidu Qianfan\": [\n \"glm-5.2\",\n \"deepseek-v4-flash\"\n ],\n \"Alibaba Tokenplan\": [\n \"glm-5.2\",\n \"deepseek-v4-flash\"\n ]\n}\n```", - "configuration.defaultModel.markdownDescription": "Default model selection to use. Must be an object with `model` and `provider`, where the provider is configured in `mutsumi.providers` and the model is listed under that provider in `mutsumi.models`.", + "configuration.providers.items.api_key.markdownDescription": "Deprecated plaintext API key. Do not add new secrets here; use the provider manager.", + "configuration.models.markdownDescription": "**Deprecated migration-only setting.** Built-in catalogs and automatic model discovery replace this mapping.", + "configuration.customProviders.markdownDescription": "Non-secret custom OpenAI-compatible provider routes. Configure API keys with **Mutsumi: Manage Model Providers**; never place keys here.", + "configuration.defaultModel.markdownDescription": "Default `{ provider, model }` selection. Configure credentials and browse supported models with **Mutsumi: Manage Model Providers**.", "configuration.titleGeneratorModel.markdownDescription": "Model selection used for generating agent titles. Must be an object with `model` and `provider`. If empty, falls back to the session metadata pair.", "configuration.compressModel.markdownDescription": "Model selection used for compressing conversations. Must be an object with `model` and `provider`. If empty, falls back to titleGeneratorModel then defaultModel.", "configuration.autoApproveEnabled.description": "Once enabled, all tool calls will be automatically approved without any confirmation (Use with caution).", diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index 29d5145..f94b241 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -16,6 +16,8 @@ "command.rejectRequest.title": "拒绝", "command.customRequestAction.title": "检查", "command.selectModel.title": "选择模型", + "command.manageProviders.title": "管理模型提供商", + "command.migrateProviderCredentials.title": "迁移提供商凭据", "command.renameSession.title": "重命名会话", "command.debugContext.title": "调试上下文", "command.pruneGhostBlocks.title": "裁剪过期引用", @@ -39,12 +41,13 @@ "command.removeShellTask.title": "移除", "configuration.title": "Mutsumi", - "configuration.providers.markdownDescription": "已配置的 LLM API 提供商\n\n示例:\n```json\n\"mutsumi.providers\": [\n {\n \"name\": \"kimi-for-coding\",\n \"baseurl\": \"https://api.kimi.com/coding/v1\",\n \"api_key\": \"sk-kimi-XXXXXXXXXXXXXXXXXXXXXX\"\n }\n]\n```", + "configuration.providers.markdownDescription": "**仅用于旧版迁移,已废弃。** 请使用“**Mutsumi: 管理模型提供商**”。现有明文密钥可通过“**Mutsumi: 迁移旧版提供商凭据**”移入 VS Code SecretStorage。", "configuration.providers.items.name.markdownDescription": "LLM API 提供商名称(例如 OpenAI、Anthropic、llama.cpp)", "configuration.providers.items.baseurl.markdownDescription": "LLM API BaseURL(例如 https://api.openai.com/v1、http://localhost:8080/v1)", - "configuration.providers.items.api_key.markdownDescription": "LLM API 密钥(必填,本地无鉴权部署可使用占位值)", - "configuration.models.markdownDescription": "提供商到模型的映射。键为 `mutsumi.providers` 中的提供商名称,值为该提供商支持的模型标识符数组。**请直接在 `settings.json` 中编辑此项。**\n\n示例:\n```json\n\"mutsumi.models\": {\n \"Baidu Qianfan\": [\n \"glm-5.2\",\n \"deepseek-v4-flash\"\n ],\n \"Alibaba Tokenplan\": [\n \"glm-5.2\",\n \"deepseek-v4-flash\"\n ]\n}\n```", - "configuration.defaultModel.markdownDescription": "默认使用的模型选择。必须是包含 `model` 与 `provider` 的对象,其中 provider 已配置在 `mutsumi.providers` 中,且 model 出现在该 provider 在 `mutsumi.models` 下对应的模型列表中。", + "configuration.providers.items.api_key.markdownDescription": "已废弃的明文 API Key。请勿在此添加新密钥,改用提供商管理命令。", + "configuration.models.markdownDescription": "**仅用于旧版迁移,已废弃。** 内置目录和自动模型发现已取代此映射。", + "configuration.customProviders.markdownDescription": "不含秘密的自定义 OpenAI-compatible 提供商路由。请通过“管理模型提供商”命令配置 API Key,切勿在此填写密钥。", + "configuration.defaultModel.markdownDescription": "默认 `{ provider, model }` 选择。请通过“**Mutsumi: 管理模型提供商**”配置凭据和浏览支持的模型。", "configuration.titleGeneratorModel.markdownDescription": "用于生成 Agent 标题的模型选择。必须是包含 `model` 与 `provider` 的对象。若为空,则回退到会话 metadata 中的模型对。", "configuration.autoApproveEnabled.description": "启用后,所有工具调用将自动批准,无需用户确认(请谨慎使用)", "configuration.compressModel.markdownDescription": "用于压缩对话的模型选择。必须是包含 `model` 与 `provider` 的对象。若为空,则依次回退到 titleGeneratorModel、defaultModel。", diff --git a/src/adapters/interfaces.ts b/src/adapters/interfaces.ts index 5eaf79e..1bc8cd3 100644 --- a/src/adapters/interfaces.ts +++ b/src/adapters/interfaces.ts @@ -14,10 +14,6 @@ import { GhostBlock } from '../contextManagement/interfaces'; export interface AgentSessionConfig { /** Model identifier for the session (e.g. gpt-4o-mini) */ model?: string; - /** API key for OpenAI-compatible endpoints */ - apiKey?: string; - /** Base URL for OpenAI-compatible endpoints */ - baseUrl?: string; /** Max tool/LLM loops allowed in a single run */ maxLoops?: number; /** Allowed URI strings for tool access */ diff --git a/src/agent/agentRunner.ts b/src/agent/agentRunner.ts index a38bcbf..318f887 100644 --- a/src/agent/agentRunner.ts +++ b/src/agent/agentRunner.ts @@ -15,7 +15,7 @@ import { LLMClient } from './llmClient'; import { IAgentSession, AgentSessionConfig } from '../adapters/interfaces'; import { LiteAgentSession } from '../adapters/liteAdapter'; import { debugLogger } from '../debugLogger'; -import { getModelCredentials, getTitleModelSelection } from '../utils'; +import { getTitleModelSelection } from '../utils'; import { AgentRunOptions } from './types'; import { t } from '../i18n'; @@ -64,10 +64,8 @@ export class AgentRunner { this.toolSet = toolSet; this.maxLoops = options.maxLoops || 30; this.llmClient = new LLMClient({ - apiKey: options.apiKey, - baseUrl: options.baseUrl, + provider: options.provider, model: options.model, - defaultHeaders: { 'User-Agent': 'KimiCLI/1.30.0' }, reasoningEffort: options.reasoningEffort }); this.uiRenderer = new UIRenderer(); @@ -120,6 +118,7 @@ export class AgentRunner { let roundContent = ''; let roundReasoning = ''; let toolCalls: any[] = []; + let replayState: import('../llm/types').PiAiReplayState | undefined; try { const result = await this.llmStreamHandler.streamResponse( @@ -144,6 +143,7 @@ export class AgentRunner { roundContent = result.roundContent; roundReasoning = result.roundReasoning; toolCalls = result.toolCalls; + replayState = result.replayState; } catch (error: any) { // Handle network/API errors gracefully const isCancellation = @@ -185,6 +185,7 @@ export class AgentRunner { if (roundReasoning) { msg.reasoning_content = roundReasoning; } + if (replayState) msg.metadata = { ...msg.metadata, piAiReplay: replayState }; messages.push(msg); newMessages.push(msg); break; @@ -195,6 +196,7 @@ export class AgentRunner { if (roundReasoning) { assistantMsg.reasoning_content = roundReasoning; } + if (replayState) assistantMsg.metadata = { ...assistantMsg.metadata, piAiReplay: replayState }; messages.push(assistantMsg); newMessages.push(assistantMsg); break; @@ -208,6 +210,7 @@ export class AgentRunner { if (roundReasoning) { assistantMsgWithTool.reasoning_content = roundReasoning; } + if (replayState) assistantMsgWithTool.metadata = { ...assistantMsgWithTool.metadata, piAiReplay: replayState }; messages.push(assistantMsgWithTool); newMessages.push(assistantMsgWithTool); diff --git a/src/agent/fileOps.ts b/src/agent/fileOps.ts index 86f76f8..9036068 100644 --- a/src/agent/fileOps.ts +++ b/src/agent/fileOps.ts @@ -138,7 +138,7 @@ export class AgentFileOperations { * 'Process files', * ['/workspace'], * 'implementer', - * { model: 'kimi-for-coding', provider: 'kimi-for-coding' }, + * { model: 'kimi-for-coding', provider: 'kimi-coding' }, * [] * ); */ diff --git a/src/agent/llmClient.ts b/src/agent/llmClient.ts index 8d06317..c8be134 100644 --- a/src/agent/llmClient.ts +++ b/src/agent/llmClient.ts @@ -1,242 +1,192 @@ -/** - * @fileoverview Generic LLM Client for unified API access. - * @module agent/llmClient - * @description Provides a unified interface for LLM operations, abstracting away - * the underlying SDK (OpenAI). This allows for easier testing, mocking, and - * potential future support for other LLM providers. - */ +/** Provider-neutral LLM client backed by pi-ai's multi-protocol catalog. */ -import OpenAI from 'openai'; -import { AgentMessage } from '../types'; +import type { AssistantMessage, SimpleStreamOptions, ThinkingLevel } from '@earendil-works/pi-ai'; +import type { AgentMessage } from '../types'; +import type { ToolDefinition } from '../tools.d/interface'; +import { toPiContext } from '../llm/context'; +import { LlmProviderService } from '../llm/providerService'; +import { toReplayState } from '../llm/replay'; +import type { PiAiReplayState } from '../llm/types'; -/** - * Configuration for LLM client. - * @interface LLMClientConfig - */ export interface LLMClientConfig { - /** API key for authentication */ - apiKey: string; - /** Base URL for the API (optional, for custom endpoints) */ - baseUrl?: string; - /** Model identifier to use */ + provider: string; model: string; - /** Default headers to include in requests */ - defaultHeaders?: Record; - /** Top-level reasoning effort value to send with completion requests */ reasoningEffort?: string; } -/** - * Options for chat completion requests. - * @interface ChatCompletionOptions - */ export interface ChatCompletionOptions { - /** Messages for the conversation */ messages: AgentMessage[]; - /** Tools/functions available to the model */ - tools?: any[]; - /** Force specific tool choice */ + tools?: ToolDefinition[]; tool_choice?: 'auto' | 'none' | { type: 'function'; function: { name: string } }; - /** Temperature for sampling (0-2) */ temperature?: number; - /** Maximum tokens to generate */ max_tokens?: number; - /** Abort signal for cancellation */ signal?: AbortSignal; } -/** - * Result of a non-streaming chat completion. - * @interface ChatCompletionResult - */ export interface ChatCompletionResult { - /** Generated message content */ content: string | null; - /** Reasoning/thinking content if available */ reasoning_content?: string; - /** Tool calls requested by the model */ tool_calls?: any[]; - /** Usage statistics */ - usage?: { - prompt_tokens: number; - completion_tokens: number; - total_tokens: number; - }; + replayState?: PiAiReplayState; + usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number }; } -/** - * Chunk from a streaming chat completion. - * @interface StreamChunk - */ export interface StreamChunk { - /** Content delta */ content?: string; - /** Reasoning content delta */ reasoning_content?: string; - /** Tool call deltas */ tool_calls?: any[]; - /** Whether this is the final chunk */ + replayState?: PiAiReplayState; done: boolean; } -/** - * Unified LLM Client for all AI operations. - * @description Encapsulates the OpenAI SDK and provides a clean interface - * for chat completions, both streaming and non-streaming. - * @class LLMClient - * @example - * const client = new LLMClient({ - * apiKey: 'sk-...', - * baseUrl: 'https://api.openai.com/v1', - * model: 'gpt-4' - * }); - * - * // Non-streaming - * const result = await client.chatCompletion({ - * messages: [{ role: 'user', content: 'Hello' }] - * }); - * - * // Streaming - * for await (const chunk of client.streamChatCompletion({ - * messages: [{ role: 'user', content: 'Hello' }] - * })) { - * console.log(chunk.content); - * } - */ +function visibleParts(message: AssistantMessage): Omit { + const texts: string[] = []; + const reasoning: string[] = []; + const toolCalls: any[] = []; + for (const block of message.content) { + if (block.type === 'text') texts.push(block.text); + else if (block.type === 'thinking') reasoning.push(block.thinking); + else toolCalls.push({ + id: block.id, + type: 'function', + function: { name: block.name, arguments: JSON.stringify(block.arguments) }, + }); + } + return { + content: texts.join('') || null, + ...(reasoning.length > 0 ? { reasoning_content: reasoning.join('') } : {}), + ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}), + replayState: toReplayState(message), + }; +} + +/** Unified LLM client whose provider identity is frozen for each request. */ export class LLMClient { - private openai: OpenAI; private model: string; - private reasoningEffort: string | undefined; + private readonly provider: string; + private readonly reasoningEffort: string | undefined; - /** - * Creates a new LLMClient instance. - * @constructor - * @param {LLMClientConfig} config - Client configuration - */ constructor(config: LLMClientConfig) { - this.openai = new OpenAI({ - apiKey: config.apiKey, - baseURL: config.baseUrl, - defaultHeaders: config.defaultHeaders || { 'User-Agent': 'KimiCLI/1.30.0' } - }); + this.provider = config.provider; this.model = config.model; this.reasoningEffort = config.reasoningEffort; } - /** - * Performs a non-streaming chat completion. - * @param {ChatCompletionOptions} options - Request options - * @returns {Promise} The completion result - * @throws {Error} If the API call fails - * @example - * const result = await client.chatCompletion({ - * messages: [ - * { role: 'system', content: 'You are helpful.' }, - * { role: 'user', content: 'Hello!' } - * ], - * temperature: 0.7 - * }); - * console.log(result.content); - */ async chatCompletion(options: ChatCompletionOptions): Promise { - const response = await this.openai.chat.completions.create({ - model: this.model, - messages: options.messages as any, - tools: options.tools, - tool_choice: options.tool_choice, - temperature: options.temperature ?? 1, - max_tokens: options.max_tokens, - ...(this.reasoningEffort !== undefined - ? { reasoning_effort: this.reasoningEffort as any } - : {}) - }, { signal: options.signal }); - - const choice = response.choices[0]; - const message = choice?.message; - + const prepared = LlmProviderService.getInstance().prepare(this.provider, this.model); + const result = await prepared.models.completeSimple( + prepared.model, + toPiContext(options.messages, options.tools), + this.streamOptions(options), + ); + if (result.stopReason === 'error' || result.stopReason === 'aborted') { + throw this.providerError(result); + } return { - content: message?.content || null, - reasoning_content: (message as any)?.reasoning_content || (message as any)?.reasoning, - tool_calls: message?.tool_calls, - usage: response.usage ? { - prompt_tokens: response.usage.prompt_tokens, - completion_tokens: response.usage.completion_tokens, - total_tokens: response.usage.total_tokens - } : undefined + ...visibleParts(result), + usage: { + prompt_tokens: result.usage.input, + completion_tokens: result.usage.output, + total_tokens: result.usage.totalTokens, + }, }; } - /** - * Performs a streaming chat completion. - * @description Returns an async iterator that yields chunks as they arrive - * from the LLM. This is useful for real-time UI updates. - * @param {ChatCompletionOptions} options - Request options - * @returns {AsyncIterableIterator} Async iterator of stream chunks - * @throws {Error} If the API call fails - * @example - * const stream = client.streamChatCompletion({ - * messages: [{ role: 'user', content: 'Tell me a story' }] - * }); - * - * for await (const chunk of stream) { - * if (chunk.content) { - * process.stdout.write(chunk.content); - * } - * if (chunk.done) { - * console.log('\n[Done]'); - * } - * } - */ async *streamChatCompletion(options: ChatCompletionOptions): AsyncIterableIterator { - const stream = await this.openai.chat.completions.create({ - model: this.model, - messages: options.messages as any, - tools: options.tools, - tool_choice: options.tool_choice, - temperature: options.temperature ?? 1, - max_tokens: options.max_tokens, - stream: true, - ...(this.reasoningEffort !== undefined - ? { reasoning_effort: this.reasoningEffort as any } - : {}) - }, { signal: options.signal }); - - for await (const chunk of stream) { - const delta = chunk.choices[0]?.delta; - - if (!delta) continue; - - const reasoningVal = (delta as any)?.reasoning_content || (delta as any)?.reasoning; - - yield { - content: delta.content ?? undefined, - reasoning_content: reasoningVal, - tool_calls: delta.tool_calls, - done: false - }; + const prepared = LlmProviderService.getInstance().prepare(this.provider, this.model); + const events = prepared.models.streamSimple( + prepared.model, + toPiContext(options.messages, options.tools), + this.streamOptions(options), + ); + const toolArgumentDeltas = new Set(); + for await (const event of events) { + switch (event.type) { + case 'text_delta': + yield { content: event.delta, done: false }; + break; + case 'thinking_delta': + yield { reasoning_content: event.delta, done: false }; + break; + case 'toolcall_start': { + const block = event.partial.content[event.contentIndex]; + if (block?.type === 'toolCall') { + yield { + tool_calls: [{ + index: event.contentIndex, + id: block.id, + type: 'function', + function: { name: block.name, arguments: '' }, + }], + done: false, + }; + } + break; + } + case 'toolcall_delta': + toolArgumentDeltas.add(event.contentIndex); + yield { + tool_calls: [{ + index: event.contentIndex, + function: { arguments: event.delta }, + }], + done: false, + }; + break; + case 'toolcall_end': + if (!toolArgumentDeltas.has(event.contentIndex)) { + yield { + tool_calls: [{ + index: event.contentIndex, + id: event.toolCall.id, + type: 'function', + function: { + name: event.toolCall.name, + arguments: JSON.stringify(event.toolCall.arguments), + }, + }], + done: false, + }; + } + break; + case 'done': + yield { replayState: toReplayState(event.message), done: true }; + return; + case 'error': + throw this.providerError(event.error); + default: + break; + } } - - yield { done: true }; + throw new Error('Provider stream ended without a terminal event'); } - /** - * Updates the model used by this client. - * @param {string} model - New model identifier - * @example - * client.setModel('gpt-4-turbo'); - */ setModel(model: string): void { this.model = model; } - /** - * Gets the current model used by this client. - * @returns {string} Current model identifier - */ getModel(): string { return this.model; } -} -// Import vscode at the end to avoid circular dependency issues -import * as vscode from 'vscode'; + private streamOptions(options: ChatCompletionOptions): SimpleStreamOptions { + const raw = this.reasoningEffort === 'none' ? 'off' : this.reasoningEffort; + const allowed = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']; + if (raw !== undefined && !allowed.includes(raw)) { + throw new Error(`Unsupported reasoning effort "${raw}"`); + } + return { + ...(raw === undefined ? {} : { reasoning: raw as ThinkingLevel }), + ...(options.temperature === undefined ? {} : { temperature: options.temperature }), + ...(options.max_tokens === undefined ? {} : { maxTokens: options.max_tokens }), + ...(options.signal === undefined ? {} : { signal: options.signal }), + maxRetries: 0, + }; + } + + private providerError(message: AssistantMessage): Error { + const error = new Error(message.errorMessage ?? `Provider stopped with ${message.stopReason}`); + if (message.stopReason === 'aborted') error.name = 'AbortError'; + return error; + } +} diff --git a/src/agent/llmStream.ts b/src/agent/llmStream.ts index fddbb4c..572005e 100644 --- a/src/agent/llmStream.ts +++ b/src/agent/llmStream.ts @@ -4,6 +4,7 @@ */ import { LLMClient, StreamChunk } from './llmClient'; +import type { PiAiReplayState } from '../llm/types'; /** * Callback function type for streaming progress updates. @@ -25,6 +26,8 @@ export interface StreamResponseResult { roundReasoning: string; /** Parsed tool calls from the response */ toolCalls: any[]; + /** Provider-native state required to safely replay this assistant turn */ + replayState?: PiAiReplayState; } /** @@ -131,7 +134,7 @@ export class LLMStreamHandler { } // Check if this is a retryable error - if (isRetryableError(error) && attempt < this.maxRetries) { + if (isRetryableError(error) && !(error as any)?.mutsumiPartialOutput && attempt < this.maxRetries) { attempt++; const delayMs = this.baseDelayMs * Math.pow(2, attempt - 1); console.warn(`LLM stream failed, retrying (${attempt}/${this.maxRetries}) after ${delayMs}ms...`, error); @@ -172,48 +175,61 @@ export class LLMStreamHandler { let currentRoundContent = ''; let currentReasoningContent = ''; + let replayState: PiAiReplayState | undefined; const toolCallBuffers: { [index: number]: any } = {}; + try { + for await (const chunk of stream) { + if (signal.aborted) { + break; + } - for await (const chunk of stream) { - if (signal.aborted) { - break; - } + let progressUpdateNeeded = false; - let progressUpdateNeeded = false; + if (chunk.replayState) replayState = chunk.replayState; - // Accumulate reasoning content - if (chunk.reasoning_content) { - currentReasoningContent += chunk.reasoning_content; - progressUpdateNeeded = true; - } + // Accumulate reasoning content + if (chunk.reasoning_content) { + currentReasoningContent += chunk.reasoning_content; + progressUpdateNeeded = true; + } - // Accumulate regular content - if (chunk.content) { - currentRoundContent += chunk.content; - progressUpdateNeeded = true; - } + // Accumulate regular content + if (chunk.content) { + currentRoundContent += chunk.content; + progressUpdateNeeded = true; + } - // Buffer tool calls from the stream - if (chunk.tool_calls) { - for (const tc of chunk.tool_calls) { - const idx = tc.index ?? 0; - if (!toolCallBuffers[idx]) { - toolCallBuffers[idx] = { ...tc, arguments: '' }; - } - if (tc.function?.name) { - toolCallBuffers[idx].function.name = tc.function.name; - } - if (tc.function?.arguments) { - toolCallBuffers[idx].function.arguments += tc.function.arguments; + // Buffer tool calls from the stream + if (chunk.tool_calls) { + for (const tc of chunk.tool_calls) { + const idx = tc.index ?? 0; + if (!toolCallBuffers[idx]) { + toolCallBuffers[idx] = { ...tc, arguments: '' }; + } + if (tc.function?.name) { + toolCallBuffers[idx].function.name = tc.function.name; + } + if (tc.function?.arguments) { + toolCallBuffers[idx].function.arguments += tc.function.arguments; + } } + progressUpdateNeeded = true; } - progressUpdateNeeded = true; - } - // Call progress callback if provided and update is needed - if (progressUpdateNeeded && onProgress) { - onProgress(currentRoundContent, currentReasoningContent, Object.values(toolCallBuffers)); + // Call progress callback if provided and update is needed + if (progressUpdateNeeded && onProgress) { + onProgress(currentRoundContent, currentReasoningContent, Object.values(toolCallBuffers)); + } + } + } catch (error) { + if (currentRoundContent || currentReasoningContent || Object.keys(toolCallBuffers).length > 0) { + const marked = error instanceof Error && Object.isExtensible(error) + ? error + : new Error(error instanceof Error ? error.message : String(error), { cause: error }); + (marked as any).mutsumiPartialOutput = true; + throw marked; } + throw error; } const rawToolCalls = Object.values(toolCallBuffers); @@ -222,7 +238,8 @@ export class LLMStreamHandler { return { roundContent: currentRoundContent, roundReasoning: currentReasoningContent, - toolCalls: finalToolCalls + toolCalls: finalToolCalls, + ...(replayState ? { replayState } : {}) }; } diff --git a/src/agent/titleGenerator.ts b/src/agent/titleGenerator.ts index b028843..b922c11 100644 --- a/src/agent/titleGenerator.ts +++ b/src/agent/titleGenerator.ts @@ -10,7 +10,7 @@ import { AgentOrchestrator } from './agentOrchestrator'; import { IAgentSession } from '../adapters/interfaces'; import { LiteAdapter } from '../adapters/liteAdapter'; import { createEmptyToolSet } from '../tools.d/toolManager'; -import { getModelCredentials, getTitleModelSelection, resolveModelSelection } from '../utils'; +import { getTitleModelSelection, resolveModelSelection } from '../utils'; import type { AgentRunOptions } from './types'; /** @@ -112,8 +112,6 @@ export async function generateTitle( const session = await adapter.createSession({ config: { model: config.model, - apiKey: config.apiKey, - baseUrl: config.baseUrl, metadata: sourceMetadata ? JSON.parse(JSON.stringify(sourceMetadata)) as AgentMetadata : undefined } }); @@ -124,8 +122,7 @@ export async function generateTitle( // Create runner options const runOptions: AgentRunOptions = { model: config.model, - apiKey: config.apiKey, - baseUrl: config.baseUrl, + provider: config.provider, maxLoops: 1 // Extra safety: limit to 1 loop }; @@ -247,21 +244,12 @@ export class TitleGenerator { const modelSelection = config.modelSelection!; - let credentials: { apiKey: string; baseUrl: string }; - try { - credentials = getModelCredentials(modelSelection.model, modelSelection.provider); - } catch (err: any) { - console.error('Failed to generate session title:', err.message); - return undefined; - } - try { // Get source metadata from notebook if available const sourceMetadata = notebook?.metadata as AgentMetadata | undefined; const title = await generateTitle(messages, { - apiKey: credentials.apiKey, - baseUrl: credentials.baseUrl, - model: modelSelection.model + model: modelSelection.model, + provider: modelSelection.provider }, sourceMetadata); await session.updateTitle(title); @@ -302,19 +290,11 @@ export async function regenerateTitleForSession( // Validate the pair through the gate before use. resolveModelSelection(modelSelection); - let credentials: { apiKey: string; baseUrl: string }; - try { - credentials = getModelCredentials(modelSelection.model, modelSelection.provider); - } catch (err: any) { - throw new Error(`Title generation failed: ${err.message}`); - } - // Get source metadata from notebook if available const sourceMetadata = notebook?.metadata as AgentMetadata | undefined; const title = await generateTitle(messages, { - apiKey: credentials.apiKey, - baseUrl: credentials.baseUrl, - model: modelSelection.model + model: modelSelection.model, + provider: modelSelection.provider }, sourceMetadata); await session.updateTitle(title); diff --git a/src/agent/toolExecutor.ts b/src/agent/toolExecutor.ts index 8037c14..9ec06d3 100644 --- a/src/agent/toolExecutor.ts +++ b/src/agent/toolExecutor.ts @@ -125,6 +125,7 @@ export class ToolExecutor { tool_call_id: tc.id, name: toolName, content: `Error: invalid tool arguments JSON: ${err.message}`, + metadata: { isError: true }, }); continue; } @@ -154,6 +155,7 @@ export class ToolExecutor { const shouldCache = this.toolSet.getShouldCache(toolName); let toolResult = ""; + let isError = false; try { if (shouldCache) { const cached = getCachedResult(toolName, toolArgs); @@ -176,8 +178,10 @@ export class ToolExecutor { if (toolSession.isAborted) { toolResult = `[Interrupted] The ${toolName} tool execution was forcibly stopped by the user.`; shouldTerminate = true; + isError = true; } else { toolResult = `Error executing tool: ${err.message}`; + isError = true; } } finally { abortSignal.removeEventListener("abort", onAgentAbort); @@ -206,6 +210,7 @@ export class ToolExecutor { tool_call_id: tc.id, name: toolName, content: toolResult, + metadata: { isError }, }); } return { messages: toolMessages, shouldTerminate, isTaskComplete }; diff --git a/src/agent/types.ts b/src/agent/types.ts index 6c9c446..3578983 100644 --- a/src/agent/types.ts +++ b/src/agent/types.ts @@ -48,10 +48,8 @@ export function normalizeReasoningEffort(value: string | undefined | null): stri export interface AgentRunOptions { /** Model identifier to use for LLM calls */ model: string; - /** OpenAI API key */ - apiKey: string; - /** Base URL for OpenAI-compatible API */ - baseUrl: string | undefined; + /** Provider route serving the selected model */ + provider: string; /** Maximum number of tool interaction loops */ maxLoops?: number; /** Reasoning effort resolved and injected by the caller; the runner does not read global configuration */ @@ -75,4 +73,4 @@ export interface DispatchSession { results: Map; /** Set of child agent UUIDs that have been deleted */ deletedChildren: Set; -} \ No newline at end of file +} diff --git a/src/config/resolver.ts b/src/config/resolver.ts index 0c05154..ad04b63 100644 --- a/src/config/resolver.ts +++ b/src/config/resolver.ts @@ -28,7 +28,7 @@ export { ResolvedAgentDefaults, ResolveAgentDefaultsOptions } from './interfaces * @example * // With overrides and filtering * const defaults = resolveAgentDefaults('implementer', { - * modelSelection: { model: 'kimi-for-coding', provider: 'kimi-for-coding' }, + * modelSelection: { model: 'kimi-for-coding', provider: 'kimi-coding' }, * availableRules: ['default.md', 'custom.md'] * }); */ diff --git a/src/config/types.ts b/src/config/types.ts index acbd184..6d3764e 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -71,7 +71,7 @@ export const DEFAULT_MUTSUMI_CONFIG: MutsumiConfig = { agentTypes: { chat: { toolSets: ["read"], - defaultModel: { model: "kimi-for-coding", provider: "kimi-for-coding" }, + defaultModel: { model: "kimi-for-coding", provider: "kimi-coding" }, defaultRules: ["default/chat.md"], defaultSkills: [], allowedChildTypes: [], @@ -79,7 +79,7 @@ export const DEFAULT_MUTSUMI_CONFIG: MutsumiConfig = { }, implementer: { toolSets: ["read", "deliver", "dispatch"], - defaultModel: { model: "kimi-for-coding", provider: "kimi-for-coding" }, + defaultModel: { model: "kimi-for-coding", provider: "kimi-coding" }, defaultRules: ["default/implementer.md"], defaultSkills: [], allowedChildTypes: ["implementer", "reviewer"], @@ -87,7 +87,7 @@ export const DEFAULT_MUTSUMI_CONFIG: MutsumiConfig = { }, orchestrator: { toolSets: ["read", "deliver", "dispatch"], - defaultModel: { model: "kimi-for-coding", provider: "kimi-for-coding" }, + defaultModel: { model: "kimi-for-coding", provider: "kimi-coding" }, defaultRules: ["default/orchestrator.md"], defaultSkills: [], allowedChildTypes: ["implementer", "reviewer"], @@ -95,7 +95,7 @@ export const DEFAULT_MUTSUMI_CONFIG: MutsumiConfig = { }, reviewer: { toolSets: ["read"], - defaultModel: { model: "kimi-for-coding", provider: "kimi-for-coding" }, + defaultModel: { model: "kimi-for-coding", provider: "kimi-coding" }, defaultRules: ["default/reviewer.md"], defaultSkills: [], allowedChildTypes: [], diff --git a/src/controller.ts b/src/controller.ts index c3ff82f..707be57 100644 --- a/src/controller.ts +++ b/src/controller.ts @@ -10,7 +10,7 @@ import { AgentOrchestrator } from './agent/agentOrchestrator'; import { NotebookAdapter } from './adapters/notebookAdapter'; import { buildInteractionHistory } from './contextManagement/history'; import { AgentMetadata } from './types'; -import { getModelCredentials, getDefaultModelSelection, resolveModelSelection } from './utils'; +import { getDefaultModelSelection, resolveModelSelection } from './utils'; import { normalizeReasoningEffort } from './agent/types'; import { t } from './i18n'; @@ -109,8 +109,6 @@ export class AgentController { resourceUri: cell.document.uri, config: { model: metadataModel ?? '', - apiKey: '', - baseUrl: '', metadata: notebook.metadata as AgentMetadata } }); @@ -119,39 +117,15 @@ export class AgentController { return; } - // Get credentials for the model - let credentials: { apiKey: string; baseUrl: string }; - try { - credentials = getModelCredentials(model, provider); - } catch (err: any) { - const adapter = new NotebookAdapter(controller); - const session = await adapter.createSession({ - resourceUri: cell.document.uri, - config: { - model, - apiKey: '', - baseUrl: '', - metadata: notebook.metadata as AgentMetadata - } - }); - await session.replaceOutput(`Error: ${err.message}`); - (session as any).end(false); - return; - } - const { apiKey, baseUrl } = credentials; - // Create adapter and session const adapter = new NotebookAdapter(controller); const session = await adapter.createSession({ resourceUri: cell.document.uri, config: { - model, - apiKey, - baseUrl, + model, metadata: notebook.metadata as AgentMetadata } }); - // getModelCredentials guarantees apiKey and baseUrl are non-empty // Get metadata and create tool set using the new Agent Type System const metadata = notebook.metadata as AgentMetadata; @@ -179,7 +153,7 @@ export class AgentController { try { const runner = new AgentRunner( - { apiKey, baseUrl, model, reasoningEffort }, + { provider, model, reasoningEffort }, toolSet, session ); diff --git a/src/extension.ts b/src/extension.ts index a87dff1..377ec53 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -37,6 +37,8 @@ import { ToolSetRegistry } from "./registry/toolSetRegistry"; import { AgentTypeRegistry } from "./registry/agentTypeRegistry"; import { resolveAgentDefaults, getEntryAgentTypes } from "./config/resolver"; import { McpRegistry } from "./mcp/registry"; +import { LlmProviderService } from "./llm/providerService"; +import { registerLegacyProviderMigration } from "./llm/migration"; /** * Checks if a file exists at the given URI. @@ -104,6 +106,11 @@ export async function activate( // Initialize ToolRegistry (required for the new ToolSet architecture) ToolRegistry.initialize(); + // Provider catalogs and SecretStorage must exist before model defaults are resolved. + const llmProviderService = LlmProviderService.getInstance(); + await llmProviderService.initialize(context); + registerLegacyProviderMigration(context); + // Validate configuration before changing either runtime registry, then connect MCP // servers before agent creation can consume their discovery snapshots. const mcpRegistry = McpRegistry.getInstance(); @@ -113,6 +120,14 @@ export async function activate( let sidebarProvider: AgentSidebarProvider | undefined; context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(async (e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration("mutsumi.customProviders")) { + try { + await llmProviderService.reload(); + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + vscode.window.showErrorMessage(`Failed to reload model providers: ${message}`); + } + } const mcpChanged = e.affectsConfiguration("mutsumi.mcpServers"); if (!mcpChanged && !e.affectsConfiguration("mutsumi.agentConfig")) return; try { diff --git a/src/httpServer/chat.ts b/src/httpServer/chat.ts index 45861d6..b5a05a8 100644 --- a/src/httpServer/chat.ts +++ b/src/httpServer/chat.ts @@ -6,7 +6,7 @@ import { RenderData, RenderBlock, MUTSUMI_AGENT_CHAT_MIME } from '../notebook/re import { ToolSet, ToolRegistry, createToolSetForAgent } from '../tools.d/toolManager'; import { getAgentFromRegistry } from './utils'; import { AgentFileOperations } from '../agent/fileOps'; -import { getModelCredentials, getDefaultModelSelection, resolveModelSelection } from '../utils'; +import { getDefaultModelSelection, resolveModelSelection } from '../utils'; import { normalizeReasoningEffort, REASONING_EFFORT_SETTING_VALUES @@ -111,17 +111,6 @@ export async function handleChat( return; } - // Get credentials for the resolved pair. - let credentials: { apiKey: string; baseUrl: string }; - try { - credentials = getModelCredentials(effectiveSelection.model, effectiveSelection.provider); - } catch (err: any) { - res.status(400).json({ status: 'error', content: err.message }); - return; - } - const { apiKey, baseUrl } = credentials; - // getModelCredentials guarantees apiKey and baseUrl are non-empty - const effectiveModel = effectiveSelection.model; const effectiveProvider = effectiveSelection.provider; const reasoningEffort = normalizeReasoningEffort( @@ -178,8 +167,6 @@ export async function handleChat( // Create session config const sessionConfig: AgentSessionConfig = { model: effectiveModel, - apiKey, - baseUrl, maxLoops, allowedUris, isSubAgent, @@ -236,8 +223,7 @@ export async function handleChat( // Create AgentRunner options const runnerOptions = { model: effectiveModel, - apiKey, - baseUrl, + provider: effectiveProvider, maxLoops, reasoningEffort }; diff --git a/src/llm/context.ts b/src/llm/context.ts new file mode 100644 index 0000000..537ee70 --- /dev/null +++ b/src/llm/context.ts @@ -0,0 +1,76 @@ +import type { Context, ImageContent, Message, TextContent, Tool } from '@earendil-works/pi-ai'; +import type { AgentMessage, MessageContent } from '../types'; +import { toPiAssistant } from './replay'; + +interface OpenAiToolDefinition { + type: 'function'; + function: { name: string; description?: string; parameters?: Record }; +} + +function decodeDataUrl(url: string): ImageContent { + const match = /^data:([^;,]+);base64,(.+)$/s.exec(url); + if (!match) throw new Error('Only base64 data URLs can be sent as image content'); + return { type: 'image', mimeType: match[1], data: match[2] }; +} + +function userContent(content: MessageContent | null): string | (TextContent | ImageContent)[] { + if (content === null || typeof content === 'string') return content ?? ''; + const parts: (TextContent | ImageContent)[] = []; + for (const part of content) { + if (part.type === 'text') { + if (part.text) parts.push({ type: 'text', text: part.text }); + } else { + parts.push(decodeDataUrl(part.image_url.url)); + } + } + return parts.every(part => part.type === 'text') + ? parts.map(part => (part as TextContent).text).join('') + : parts; +} + +function textContent(content: MessageContent | null): string { + if (content === null) return ''; + if (typeof content === 'string') return content; + return content.filter(part => part.type === 'text').map(part => part.text).join(''); +} + +/** Convert Mutsumi's durable history and OpenAI-shaped tool schemas into pi-ai Context. */ +export function toPiContext(messages: AgentMessage[], tools: OpenAiToolDefinition[] = []): Context { + const converted: Message[] = []; + const leadingSystem: string[] = []; + let sawConversation = false; + for (const message of messages) { + if (message.role === 'system' && !sawConversation) { + leadingSystem.push(textContent(message.content)); + continue; + } + sawConversation = true; + if (message.role === 'system') { + converted.push({ role: 'user', content: textContent(message.content), timestamp: 0 }); + } else if (message.role === 'user') { + converted.push({ role: 'user', content: userContent(message.content), timestamp: 0 }); + } else if (message.role === 'assistant') { + converted.push(toPiAssistant(message)); + } else { + converted.push({ + role: 'toolResult', + toolCallId: message.tool_call_id ?? '', + toolName: message.name ?? 'unknown', + content: [{ type: 'text', text: textContent(message.content) || '(no output)' }], + isError: message.metadata?.isError === true + || /^(?:Error:|\[Interrupted\])/.test(textContent(message.content)), + timestamp: 0, + }); + } + } + const piTools: Tool[] = tools.map(tool => ({ + name: tool.function.name, + description: tool.function.description ?? '', + parameters: (tool.function.parameters ?? { type: 'object', properties: {} }) as Tool['parameters'], + })); + return { + ...(leadingSystem.length > 0 ? { systemPrompt: leadingSystem.join('\n\n') } : {}), + messages: converted, + ...(piTools.length > 0 ? { tools: piTools } : {}), + }; +} diff --git a/src/llm/credentialStore.ts b/src/llm/credentialStore.ts new file mode 100644 index 0000000..af3c8b1 --- /dev/null +++ b/src/llm/credentialStore.ts @@ -0,0 +1,87 @@ +import type * as vscode from 'vscode'; +import type { Credential, CredentialInfo, CredentialStore } from '@earendil-works/pi-ai'; + +const SECRET_PREFIX = 'mutsumi.llmCredential.'; +const INDEX_KEY = 'mutsumi.llmCredentialProviders.v1'; + +/** pi-ai credential store backed by VS Code's encrypted SecretStorage. */ +export class VsCodeCredentialStore implements CredentialStore { + private readonly queues = new Map>(); + + constructor( + private readonly secrets: vscode.SecretStorage, + private readonly globalState: vscode.Memento, + ) {} + + async read(providerId: string): Promise { + const raw = await this.secrets.get(this.key(providerId)); + if (!raw) return undefined; + try { + const value: unknown = JSON.parse(raw); + if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined; + const type = (value as { type?: unknown }).type; + return type === 'api_key' || type === 'oauth' ? value as Credential : undefined; + } catch { + return undefined; + } + } + + async list(): Promise { + const ids = this.globalState.get(INDEX_KEY, []); + const result: CredentialInfo[] = []; + for (const providerId of ids) { + const credential = await this.read(providerId); + if (credential) result.push({ providerId, type: credential.type }); + } + return result; + } + + modify( + providerId: string, + fn: (current: Credential | undefined) => Promise, + ): Promise { + return this.serialized(providerId, async () => { + const next = await fn(await this.read(providerId)); + if (next === undefined) return this.read(providerId); + await this.secrets.store(this.key(providerId), JSON.stringify(next)); + await this.addToIndex(providerId); + return next; + }); + } + + delete(providerId: string): Promise { + return this.serialized(providerId, async () => { + await this.secrets.delete(this.key(providerId)); + const ids = this.globalState.get(INDEX_KEY, []); + await this.globalState.update(INDEX_KEY, ids.filter(id => id !== providerId)); + }); + } + + /** Store a legacy API key without ever projecting it into ordinary settings. */ + async storeApiKey(providerId: string, key: string): Promise { + await this.modify(providerId, async current => ({ + type: 'api_key', + ...current?.type === 'api_key' && current.env ? { env: current.env } : {}, + key, + })); + } + + private key(providerId: string): string { + return `${SECRET_PREFIX}${encodeURIComponent(providerId)}`; + } + + private async addToIndex(providerId: string): Promise { + const ids = this.globalState.get(INDEX_KEY, []); + if (!ids.includes(providerId)) await this.globalState.update(INDEX_KEY, [...ids, providerId]); + } + + private serialized(providerId: string, operation: () => Promise): Promise { + const previous = this.queues.get(providerId) ?? Promise.resolve(); + const next = previous.catch(() => undefined).then(operation); + const tracked = next.finally(() => { + if (this.queues.get(providerId) === tracked) this.queues.delete(providerId); + }); + this.queues.set(providerId, tracked); + return next; + } +} diff --git a/src/llm/migration.ts b/src/llm/migration.ts new file mode 100644 index 0000000..187fe96 --- /dev/null +++ b/src/llm/migration.ts @@ -0,0 +1,165 @@ +import * as vscode from 'vscode'; +import { t } from '../i18n'; +import { LlmProviderService } from './providerService'; +import type { CustomProviderProfile } from './types'; + +interface LegacyProvider { + name: string; + baseurl: string; + api_key?: string; +} + +interface Layer { + target: vscode.ConfigurationTarget; + resource?: vscode.Uri; + providers: LegacyProvider[]; + models: Record; + customProviders: Record; +} + +const PROMPTED_KEY = 'mutsumi.legacyCredentialMigration.prompted.v1'; +const DEFAULT_KIMI_URL = 'https://api.kimi.com/coding/v1'; + +function inspectLayers(resource?: vscode.Uri, includeShared = true): Layer[] { + const config = vscode.workspace.getConfiguration('mutsumi', resource); + const providers = config.inspect('providers'); + const models = config.inspect>('models'); + const custom = config.inspect>('customProviders'); + const layers: Layer[] = []; + const add = ( + target: vscode.ConfigurationTarget, + providerValue: LegacyProvider[] | undefined, + modelValue: Record | undefined, + customValue: Record | undefined, + ) => { + if (Array.isArray(providerValue) && providerValue.length > 0) { + layers.push({ target, resource, providers: providerValue, models: modelValue ?? {}, customProviders: customValue ?? {} }); + } + }; + if (includeShared) { + add(vscode.ConfigurationTarget.Global, providers?.globalValue, models?.globalValue, custom?.globalValue); + add(vscode.ConfigurationTarget.Workspace, providers?.workspaceValue, models?.workspaceValue, custom?.workspaceValue); + } + add(vscode.ConfigurationTarget.WorkspaceFolder, providers?.workspaceFolderValue, models?.workspaceFolderValue, custom?.workspaceFolderValue); + return layers; +} + +function allLayers(): Layer[] { + const layers = inspectLayers(undefined, true).filter(layer => layer.target !== vscode.ConfigurationTarget.WorkspaceFolder); + for (const folder of vscode.workspace.workspaceFolders ?? []) { + layers.push(...inspectLayers(folder.uri, false)); + } + return layers; +} + +function secretConflicts(layers: Layer[]): string[] { + const keys = new Map>(); + for (const layer of layers) for (const provider of layer.providers) { + if (!provider.api_key) continue; + const route = provider.name === 'kimi-for-coding' && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL + ? 'kimi-coding' + : provider.name; + const values = keys.get(route) ?? new Set(); + values.add(provider.api_key); + keys.set(route, values); + } + return [...keys].filter(([, values]) => values.size > 1).map(([route]) => route); +} + +/** Move legacy plaintext provider credentials into SecretStorage, then remove their settings. */ +export async function migrateLegacyProviders(): Promise { + const layers = allLayers(); + if (layers.length === 0) return false; + const conflicts = secretConflicts(layers); + if (conflicts.length > 0) { + throw new Error(t('migration.conflicts', conflicts.join(', '))); + } + + const service = LlmProviderService.getInstance(); + const reservedLegacyRoutes = layers.flatMap(layer => layer.providers).filter(provider => { + const isDefaultKimi = provider.name === 'kimi-for-coding' + && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL; + return !isDefaultKimi && service.isBuiltInProviderId(provider.name); + }).map(provider => provider.name); + if (reservedLegacyRoutes.length > 0) { + throw new Error(t('migration.routeConflicts', [...new Set(reservedLegacyRoutes)].join(', '))); + } + const credentials = service.getCredentialStore(); + // Store every secret first. Configuration remains untouched if any secure write fails. + for (const layer of layers) for (const provider of layer.providers) { + if (!provider.api_key) continue; + const isDefaultKimi = provider.name === 'kimi-for-coding' + && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL; + await credentials.storeApiKey(isDefaultKimi ? 'kimi-coding' : provider.name, provider.api_key); + } + + const migratedCustom = new Map>(); + for (const layer of layers) { + const customProviders = { ...layer.customProviders }; + for (const provider of layer.providers) { + const isDefaultKimi = provider.name === 'kimi-for-coding' + && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL; + if (isDefaultKimi) continue; + customProviders[provider.name] = { + displayName: provider.name, + baseUrl: provider.baseurl, + api: 'openai-completions', + auth: 'apiKey', + models: layer.models[provider.name] ?? [], + }; + } + migratedCustom.set(layer, customProviders); + } + + // Finish every non-secret write before removing any legacy value. + for (const [layer, customProviders] of migratedCustom) { + await vscode.workspace.getConfiguration('mutsumi', layer.resource) + .update('customProviders', customProviders, layer.target); + } + + const cleared: Layer[] = []; + try { + for (const layer of layers) { + const config = vscode.workspace.getConfiguration('mutsumi', layer.resource); + cleared.push(layer); + await config.update('providers', undefined, layer.target); + await config.update('models', undefined, layer.target); + } + } catch (error) { + // Best-effort rollback ensures a partial settings failure does not silently discard secrets. + for (const layer of cleared.reverse()) { + const config = vscode.workspace.getConfiguration('mutsumi', layer.resource); + try { await config.update('providers', layer.providers, layer.target); } catch { /* best effort */ } + try { await config.update('models', layer.models, layer.target); } catch { /* best effort */ } + } + throw error; + } + await service.reload(); + void vscode.window.showWarningMessage( + t('migration.rotationWarning'), + ); + return true; +} + +/** Register the manual migration command and show the one-time activation prompt. */ +export function registerLegacyProviderMigration(context: vscode.ExtensionContext): void { + const run = async () => { + try { + const migrated = await migrateLegacyProviders(); + if (!migrated) void vscode.window.showInformationMessage(t('migration.noneFound')); + } catch (error: any) { + void vscode.window.showErrorMessage(t('migration.failed', error.message ?? String(error))); + } + }; + context.subscriptions.push(vscode.commands.registerCommand('mutsumi.migrateProviderCredentials', run)); + if (allLayers().length === 0 + || context.globalState.get(PROMPTED_KEY, false)) return; + void context.globalState.update(PROMPTED_KEY, true).then(async () => { + const migrate = t('migration.action'); + const selected = await vscode.window.showWarningMessage( + t('migration.prompt'), + migrate, + ); + if (selected === migrate) await run(); + }); +} diff --git a/src/llm/modelStore.ts b/src/llm/modelStore.ts new file mode 100644 index 0000000..645a7eb --- /dev/null +++ b/src/llm/modelStore.ts @@ -0,0 +1,26 @@ +import type * as vscode from 'vscode'; +import type { ModelsStore, ModelsStoreEntry } from '@earendil-works/pi-ai'; + +const CACHE_PREFIX = 'mutsumi.llmModels.v1.'; + +/** Non-secret persistent cache for dynamically discovered model catalogs. */ +export class VsCodeModelsStore implements ModelsStore { + constructor(private readonly globalState: vscode.Memento) {} + + read(providerId: string): Promise { + const value = this.globalState.get(this.key(providerId)); + return Promise.resolve(value); + } + + async write(providerId: string, entry: ModelsStoreEntry): Promise { + await this.globalState.update(this.key(providerId), entry); + } + + async delete(providerId: string): Promise { + await this.globalState.update(this.key(providerId), undefined); + } + + private key(providerId: string): string { + return `${CACHE_PREFIX}${encodeURIComponent(providerId)}`; + } +} diff --git a/src/llm/providerService.ts b/src/llm/providerService.ts new file mode 100644 index 0000000..e1a0a9f --- /dev/null +++ b/src/llm/providerService.ts @@ -0,0 +1,431 @@ +import * as vscode from 'vscode'; +import { + createModels, + createProvider, + getSupportedThinkingLevels, +} from '@earendil-works/pi-ai'; +import type { + Api, + AuthInteraction, + Credential, + Model, + Models, + MutableModels, + Provider, + RefreshModelsContext, +} from '@earendil-works/pi-ai'; +import { builtinProviders } from '@earendil-works/pi-ai/providers/all'; +import * as openaiCompletions from '@earendil-works/pi-ai/api/openai-completions'; +import * as openaiResponses from '@earendil-works/pi-ai/api/openai-responses'; +import type { ModelSelection } from '../types'; +import { VsCodeCredentialStore } from './credentialStore'; +import { VsCodeModelsStore } from './modelStore'; +import type { CustomProviderProfile, ModelInfo, ProviderInfo } from './types'; + +const DEFAULT_CONTEXT_WINDOW = 262_144; +const DEFAULT_MAX_TOKENS = 32_768; +const DISCOVERY_LIMIT = 4 * 1024 * 1024; +const DISCOVERY_TIMEOUT_MS = 15_000; +const LEGACY_PROVIDER_ALIASES: Readonly> = { + 'kimi-for-coding': 'kimi-coding', +}; +const NO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }; + +interface Snapshot { + models: MutableModels; + providers: ReadonlyMap; + customProfiles: ReadonlyMap; +} + +interface ListingEntry { + id?: unknown; + name?: unknown; + display_name?: unknown; + context_window?: unknown; + context_length?: unknown; + max_tokens?: unknown; + max_output_tokens?: unknown; +} + +/** Extension-level owner of provider catalogs, credentials, and LLM dispatch. */ +export class LlmProviderService { + private static instance: LlmProviderService | undefined; + + private snapshot: Snapshot | undefined; + private credentialStore: VsCodeCredentialStore | undefined; + private modelsStore: VsCodeModelsStore | undefined; + private context: vscode.ExtensionContext | undefined; + + static getInstance(): LlmProviderService { + LlmProviderService.instance ??= new LlmProviderService(); + return LlmProviderService.instance; + } + + async initialize(context: vscode.ExtensionContext): Promise { + this.context = context; + this.credentialStore = new VsCodeCredentialStore(context.secrets, context.globalState); + this.modelsStore = new VsCodeModelsStore(context.globalState); + await this.reload(); + } + + /** Build a complete candidate registry, restore cached catalogs, then publish atomically. */ + async reload(): Promise { + const credentials = this.requireCredentialStore(); + const modelsStore = this.requireModelsStore(); + const rawProfiles = vscode.workspace.getConfiguration('mutsumi') + .get>('customProviders', {}); + const customProfiles = this.validateProfiles(rawProfiles); + const models = createModels({ credentials, modelsStore }); + const providers = new Map(); + + for (const provider of builtinProviders()) { + if (!provider.auth.apiKey) continue; + providers.set(provider.id, provider); + models.setProvider(provider); + } + for (const [id, profile] of customProfiles) { + if (providers.has(id) || LEGACY_PROVIDER_ALIASES[id]) { + throw new Error(`Custom provider "${id}" conflicts with a built-in provider`); + } + const provider = this.createCustomProvider(id, profile); + providers.set(id, provider); + models.setProvider(provider); + } + + await models.refresh({ allowNetwork: false }); + this.snapshot = { models, providers, customProfiles }; + } + + canonicalProvider(provider: string): string { + return LEGACY_PROVIDER_ALIASES[provider] ?? provider; + } + + resolveSelection(selection: ModelSelection): ModelSelection & { modelInfo: ModelInfo } { + const provider = this.canonicalProvider(selection.provider.trim()); + const model = selection.model.trim(); + if (!provider || !model) throw new Error('Model and provider must be non-empty strings'); + const resolved = this.requireSnapshot().models.getModel(provider, model); + if (!resolved) throw new Error(`Model "${model}" is not available from provider "${provider}"`); + return { provider, model, modelInfo: this.toModelInfo(resolved) }; + } + + getModel(provider: string, model: string): Model { + const canonical = this.canonicalProvider(provider); + const resolved = this.requireSnapshot().models.getModel(canonical, model); + if (!resolved) throw new Error(`Model "${model}" is not available from provider "${canonical}"`); + return resolved; + } + + /** Capture the registry and model used by one request so config reloads cannot split it. */ + prepare(provider: string, model: string): { models: Models; model: Model; provider: string } { + const snapshot = this.requireSnapshot(); + const canonical = this.canonicalProvider(provider); + const resolved = snapshot.models.getModel(canonical, model); + if (!resolved) throw new Error(`Model "${model}" is not available from provider "${canonical}"`); + return { models: snapshot.models, model: resolved, provider: canonical }; + } + + async listProviders(): Promise { + const snapshot = this.requireSnapshot(); + const result: ProviderInfo[] = []; + for (const provider of snapshot.providers.values()) { + let authSource: string | undefined; + let configured = false; + try { + const auth = await snapshot.models.checkAuth(provider.id); + configured = auth !== undefined; + authSource = auth?.source; + } catch { + authSource = undefined; + } + result.push({ + id: provider.id, + name: provider.name, + isCustom: snapshot.customProfiles.has(provider.id), + isDynamic: provider.refreshModels !== undefined, + configured, + canConfigureApiKey: provider.auth.apiKey?.login !== undefined, + ...(authSource ? { authSource } : {}), + modelCount: snapshot.models.getModels(provider.id).length, + }); + } + return result.sort((a, b) => a.name.localeCompare(b.name)); + } + + async listAvailableModels(autoRefresh = true): Promise { + let snapshot = this.requireSnapshot(); + let available = await snapshot.models.getAvailable(); + let needsRefresh = false; + if (autoRefresh) { + for (const provider of snapshot.providers.values()) { + if (!provider.refreshModels || snapshot.models.getModels(provider.id).length > 0) continue; + try { + if (await snapshot.models.checkAuth(provider.id)) { + needsRefresh = true; + break; + } + } catch { + // Authentication diagnostics are surfaced by provider management. + } + } + } + if (needsRefresh) { + await this.refreshModels(); + snapshot = this.requireSnapshot(); + available = await snapshot.models.getAvailable(); + } + return available.map(model => this.toModelInfo(model)); + } + + listModels(provider: string): ModelInfo[] { + return this.requireSnapshot().models + .getModels(this.canonicalProvider(provider)) + .map(model => this.toModelInfo(model)); + } + + isBuiltInProviderId(provider: string): boolean { + const canonical = this.canonicalProvider(provider); + const snapshot = this.requireSnapshot(); + return snapshot.providers.has(canonical) && !snapshot.customProfiles.has(canonical); + } + + async configureApiKey(provider: string, interaction: AuthInteraction): Promise { + const canonical = this.canonicalProvider(provider); + const snapshot = this.requireSnapshot(); + const entry = snapshot.providers.get(canonical); + if (!entry?.auth.apiKey?.login) throw new Error(`Provider "${canonical}" does not support API-key setup`); + await snapshot.models.login(canonical, 'api_key', interaction); + if (entry.refreshModels) return (await this.refreshModels()).get(canonical); + return undefined; + } + + async deleteCredential(provider: string): Promise { + await this.requireSnapshot().models.logout(this.canonicalProvider(provider)); + } + + async refreshModels(): Promise> { + const result = await this.requireSnapshot().models.refresh({ allowNetwork: true, force: true }); + return result.errors; + } + + async deleteCachedModels(provider: string): Promise { + await this.requireModelsStore().delete(this.canonicalProvider(provider)); + } + + getCredentialStore(): VsCodeCredentialStore { + return this.requireCredentialStore(); + } + + private validateProfiles(raw: Record): Map { + if (!raw || typeof raw !== 'object' || Array.isArray(raw)) { + throw new Error('mutsumi.customProviders must be an object keyed by provider route'); + } + const result = new Map(); + for (const [untrimmedId, profile] of Object.entries(raw)) { + const id = untrimmedId.trim(); + if (!id) throw new Error('Custom provider IDs must be non-empty'); + if (result.has(id)) throw new Error(`Custom provider route "${id}" is duplicated after trimming`); + if (!profile || typeof profile !== 'object' || Array.isArray(profile)) { + throw new Error(`Custom provider "${id}" must be an object`); + } + const baseUrl = typeof profile.baseUrl === 'string' ? profile.baseUrl.trim() : ''; + if (!baseUrl) throw new Error(`Custom provider "${id}" has an empty baseUrl`); + let parsedUrl: URL; + try { + parsedUrl = new URL(baseUrl); + } catch { + throw new Error(`Custom provider "${id}" has an invalid baseUrl`); + } + if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') { + throw new Error(`Custom provider "${id}" baseUrl must use HTTP(S)`); + } + if (parsedUrl.username || parsedUrl.password) { + throw new Error(`Custom provider "${id}" baseUrl must not contain credentials`); + } + const api = profile.api ?? 'openai-completions'; + if (api !== 'openai-completions' && api !== 'openai-responses') { + throw new Error(`Custom provider "${id}" has unsupported api "${String(profile.api)}"`); + } + const auth = profile.auth ?? 'apiKey'; + if (auth !== 'apiKey' && auth !== 'none') { + throw new Error(`Custom provider "${id}" has unsupported auth "${String(profile.auth)}"`); + } + const models = profile.models ?? []; + if (!Array.isArray(models) || models.some(model => typeof model !== 'string' || !model.trim())) { + throw new Error(`Custom provider "${id}" models must contain non-empty strings`); + } + result.set(id, { + ...profile.displayName?.trim() ? { displayName: profile.displayName.trim() } : {}, + baseUrl, + api, + auth, + models: [...new Set(models.map(model => model.trim()))], + }); + } + return result; + } + + private createCustomProvider(id: string, profile: CustomProviderProfile): Provider { + const api = profile.api ?? 'openai-completions'; + const models = (profile.models ?? []).map(modelId => this.customModel(id, profile, modelId)); + const auth = profile.auth ?? 'apiKey'; + return createProvider({ + id, + name: profile.displayName ?? id, + baseUrl: profile.baseUrl, + auth: { + apiKey: auth === 'none' ? { + name: 'No authentication', + check: async () => ({ type: 'api_key', source: 'No authentication' }), + resolve: async () => ({ auth: {}, source: 'No authentication' }), + } : { + name: `${profile.displayName ?? id} API key`, + login: async interaction => ({ + type: 'api_key', + key: await interaction.prompt({ + type: 'secret', + message: `Enter the API key for ${profile.displayName ?? id}`, + }), + }), + check: async ({ credential }) => credential?.key + ? { type: 'api_key', source: 'VS Code SecretStorage' } + : undefined, + resolve: async ({ credential }) => credential?.key + ? { auth: { apiKey: credential.key }, source: 'VS Code SecretStorage' } + : undefined, + }, + }, + models, + fetchModels: context => this.discoverCustomModels(id, profile, context), + api: api === 'openai-responses' ? openaiResponses : openaiCompletions, + }); + } + + private customModel(id: string, profile: CustomProviderProfile, modelId: string, entry?: ListingEntry): Model { + const api = profile.api ?? 'openai-completions'; + return { + id: modelId, + name: this.label(entry?.name, entry?.display_name) ?? modelId, + api, + provider: id, + baseUrl: profile.baseUrl, + reasoning: false, + input: ['text'], + cost: NO_COST, + contextWindow: this.capacity(entry?.context_window, entry?.context_length) ?? DEFAULT_CONTEXT_WINDOW, + maxTokens: this.capacity(entry?.max_output_tokens, entry?.max_tokens) ?? DEFAULT_MAX_TOKENS, + }; + } + + private async discoverCustomModels( + id: string, + profile: CustomProviderProfile, + context: RefreshModelsContext, + ): Promise[]> { + const url = `${profile.baseUrl.replace(/\/+$/, '')}/models`; + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), DISCOVERY_TIMEOUT_MS); + const signal = context.signal ? AbortSignal.any([context.signal, controller.signal]) : controller.signal; + const key = context.credential?.type === 'api_key' ? context.credential.key : undefined; + try { + const response = await fetch(url, { + headers: { + accept: 'application/json', + ...(key ? { authorization: `Bearer ${key}` } : {}), + }, + signal, + }); + if (!response.ok) { + throw new Error(`${url} returned HTTP ${response.status}${response.status === 401 || response.status === 403 ? '; check the API key' : ''}`); + } + const text = await this.readBounded(response, url); + let value: unknown; + try { + value = JSON.parse(text); + } catch (error) { + throw new Error(`${url} did not return JSON`, { cause: error }); + } + const data = (value as { data?: unknown } | null)?.data; + if (!Array.isArray(data)) throw new Error(`${url} model listing has no data array`); + const result: Model[] = []; + const seen = new Set(); + for (const raw of data) { + const entry = raw as ListingEntry | null; + const modelId = this.label(entry?.id); + if (!modelId || seen.has(modelId)) continue; + seen.add(modelId); + result.push(this.customModel(id, profile, modelId, entry ?? undefined)); + } + if (result.length === 0) throw new Error(`${url} returned no usable model IDs`); + return result; + } finally { + clearTimeout(timeout); + } + } + + private async readBounded(response: Response, url: string): Promise { + const declared = Number(response.headers.get('content-length') ?? Number.NaN); + if (Number.isFinite(declared) && declared > DISCOVERY_LIMIT) { + await response.body?.cancel(); + throw new Error(`${url} returned more than ${DISCOVERY_LIMIT} bytes`); + } + if (!response.body) return ''; + const reader = response.body.getReader(); + const chunks: Uint8Array[] = []; + let total = 0; + for (;;) { + const { done, value } = await reader.read(); + if (done) break; + total += value.byteLength; + if (total > DISCOVERY_LIMIT) { + await reader.cancel(); + throw new Error(`${url} returned more than ${DISCOVERY_LIMIT} bytes`); + } + chunks.push(value); + } + const body = new Uint8Array(total); + let offset = 0; + for (const chunk of chunks) { + body.set(chunk, offset); + offset += chunk.byteLength; + } + return new TextDecoder().decode(body); + } + + private capacity(...values: unknown[]): number | undefined { + return values.find(value => typeof value === 'number' && Number.isInteger(value) && value > 0) as number | undefined; + } + + private label(...values: unknown[]): string | undefined { + return values.find(value => typeof value === 'string' && value.trim())?.toString().trim(); + } + + private toModelInfo(model: Model): ModelInfo { + return { + id: model.id, + name: model.name, + provider: model.provider, + input: [...model.input], + contextWindow: model.contextWindow, + maxTokens: model.maxTokens, + reasoningEfforts: model.reasoning + ? getSupportedThinkingLevels(model).map(level => level === 'off' ? 'none' : level) + : [], + }; + } + + private requireSnapshot(): Snapshot { + if (!this.snapshot) throw new Error('LLM provider service has not been initialized'); + return this.snapshot; + } + + private requireCredentialStore(): VsCodeCredentialStore { + if (!this.credentialStore) throw new Error('LLM credential store has not been initialized'); + return this.credentialStore; + } + + private requireModelsStore(): VsCodeModelsStore { + if (!this.modelsStore) throw new Error('LLM model store has not been initialized'); + return this.modelsStore; + } +} diff --git a/src/llm/replay.ts b/src/llm/replay.ts new file mode 100644 index 0000000..3e1f288 --- /dev/null +++ b/src/llm/replay.ts @@ -0,0 +1,169 @@ +import type { Api, AssistantMessage, ToolCall, Usage } from '@earendil-works/pi-ai'; +import type { AgentMessage } from '../types'; +import type { PiAiReplayBlock, PiAiReplayState } from './types'; + +function emptyUsage(): Usage { + return { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + totalTokens: 0, + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, + }; +} + +function parseArguments(raw: unknown): Record { + if (typeof raw !== 'string') return {}; + try { + const value: unknown = JSON.parse(raw); + return value && typeof value === 'object' && !Array.isArray(value) + ? value as Record + : {}; + } catch { + return {}; + } +} + +/** Project the successful native response into JSON-safe durable replay metadata. */ +export function toReplayState(message: AssistantMessage): PiAiReplayState { + return { + kind: 'pi-ai', + version: 1, + api: message.api, + provider: message.provider, + model: message.model, + ...(message.responseModel === undefined ? {} : { responseModel: message.responseModel }), + ...(message.responseId === undefined ? {} : { responseId: message.responseId }), + stopReason: message.stopReason, + blocks: message.content.map((block): PiAiReplayBlock => { + switch (block.type) { + case 'text': return { + type: 'text', + text: block.text, + ...(block.textSignature === undefined ? {} : { textSignature: block.textSignature }), + }; + case 'thinking': return { + type: 'reasoning', + text: block.thinking, + ...(block.thinkingSignature === undefined ? {} : { thinkingSignature: block.thinkingSignature }), + ...(block.redacted === undefined ? {} : { redacted: block.redacted }), + }; + case 'toolCall': return { + type: 'tool-call', + id: block.id, + name: block.name, + arguments: block.arguments, + ...(block.thoughtSignature === undefined ? {} : { thoughtSignature: block.thoughtSignature }), + }; + } + }), + }; +} + +function visibleText(message: AgentMessage): string { + if (typeof message.content === 'string') return message.content; + if (!Array.isArray(message.content)) return ''; + return message.content.filter(part => part.type === 'text').map(part => part.text).join(''); +} + +function stateMatchesVisible(message: AgentMessage, state: PiAiReplayState): boolean { + const text = state.blocks.filter(block => block.type === 'text').map(block => block.text).join(''); + const reasoning = state.blocks.filter(block => block.type === 'reasoning').map(block => block.text).join(''); + const tools = state.blocks.filter((block): block is Extract => block.type === 'tool-call'); + if (text !== visibleText(message) || reasoning !== (message.reasoning_content ?? '')) return false; + const visibleTools = message.tool_calls ?? []; + if (tools.length !== visibleTools.length) return false; + return tools.every((tool, index) => { + const visible = visibleTools[index]; + return visible?.id === tool.id + && visible?.function?.name === tool.name + && JSON.stringify(parseArguments(visible?.function?.arguments)) === JSON.stringify(tool.arguments); + }); +} + +function readReplayState(message: AgentMessage): PiAiReplayState | undefined { + const value: unknown = message.metadata?.piAiReplay; + if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined; + const state = value as Partial; + if (state.kind !== 'pi-ai' || state.version !== 1) return undefined; + if (typeof state.api !== 'string' || typeof state.provider !== 'string' || typeof state.model !== 'string') return undefined; + if (!Array.isArray(state.blocks)) return undefined; + const validBlocks = state.blocks.every(block => { + if (!block || typeof block !== 'object') return false; + if (block.type === 'text' || block.type === 'reasoning') return typeof block.text === 'string'; + return block.type === 'tool-call' + && typeof block.id === 'string' + && typeof block.name === 'string' + && !!block.arguments + && typeof block.arguments === 'object' + && !Array.isArray(block.arguments); + }); + if (!validBlocks || !stateMatchesVisible(message, state as PiAiReplayState)) return undefined; + return state as PiAiReplayState; +} + +function replayedAssistant(state: PiAiReplayState): AssistantMessage { + return { + role: 'assistant', + api: state.api, + provider: state.provider, + model: state.model, + ...(state.responseModel === undefined ? {} : { responseModel: state.responseModel }), + ...(state.responseId === undefined ? {} : { responseId: state.responseId }), + stopReason: state.stopReason, + usage: emptyUsage(), + timestamp: 0, + content: state.blocks.map(block => { + switch (block.type) { + case 'text': return { + type: 'text' as const, + text: block.text, + ...(block.textSignature === undefined ? {} : { textSignature: block.textSignature }), + }; + case 'reasoning': return { + type: 'thinking' as const, + thinking: block.text, + ...(block.thinkingSignature === undefined ? {} : { thinkingSignature: block.thinkingSignature }), + ...(block.redacted === undefined ? {} : { redacted: block.redacted }), + }; + case 'tool-call': return { + type: 'toolCall' as const, + id: block.id, + name: block.name, + arguments: block.arguments, + ...(block.thoughtSignature === undefined ? {} : { thoughtSignature: block.thoughtSignature }), + }; + } + }), + }; +} + +/** Reconstruct a native assistant turn, trusting replay metadata only when visible data still matches. */ +export function toPiAssistant(message: AgentMessage): AssistantMessage { + const state = readReplayState(message); + if (state) return replayedAssistant(state); + const content: AssistantMessage['content'] = []; + if (message.reasoning_content) content.push({ type: 'thinking', thinking: message.reasoning_content }); + const text = visibleText(message); + if (text) content.push({ type: 'text', text }); + for (const raw of message.tool_calls ?? []) { + const tool: ToolCall = { + type: 'toolCall', + id: typeof raw?.id === 'string' ? raw.id : '', + name: typeof raw?.function?.name === 'string' ? raw.function.name : '', + arguments: parseArguments(raw?.function?.arguments), + }; + content.push(tool); + } + return { + role: 'assistant', + content, + api: 'mutsumi-foreign' as Api, + provider: 'mutsumi-foreign', + model: 'mutsumi-foreign', + usage: emptyUsage(), + stopReason: (message.tool_calls?.length ?? 0) > 0 ? 'toolUse' : 'stop', + timestamp: 0, + }; +} diff --git a/src/llm/types.ts b/src/llm/types.ts new file mode 100644 index 0000000..f90e9f2 --- /dev/null +++ b/src/llm/types.ts @@ -0,0 +1,61 @@ +import type { Api, AssistantMessage } from '@earendil-works/pi-ai'; + +/** Non-secret configuration for a user-defined OpenAI-compatible route. */ +export interface CustomProviderProfile { + displayName?: string; + baseUrl: string; + api?: 'openai-completions' | 'openai-responses'; + auth?: 'apiKey' | 'none'; + models?: string[]; +} + +/** Provider information suitable for selectors and status UI. */ +export interface ProviderInfo { + id: string; + name: string; + isCustom: boolean; + isDynamic: boolean; + configured: boolean; + canConfigureApiKey: boolean; + authSource?: string; + modelCount: number; +} + +/** Model information exposed to Mutsumi UI and configuration validation. */ +export interface ModelInfo { + id: string; + name: string; + provider: string; + input: readonly ('text' | 'image')[]; + contextWindow: number; + maxTokens: number; + reasoningEfforts: readonly string[]; +} + +export type PiAiReplayBlock = + | { type: 'text'; text: string; textSignature?: string } + | { type: 'reasoning'; text: string; thinkingSignature?: string; redacted?: boolean } + | { type: 'tool-call'; id: string; name: string; arguments: Record; thoughtSignature?: string }; + +/** Versioned provider-native state required for safe multi-turn replay. */ +export interface PiAiReplayState { + kind: 'pi-ai'; + version: 1; + api: Api; + provider: string; + model: string; + responseModel?: string; + responseId?: string; + stopReason: AssistantMessage['stopReason']; + blocks: PiAiReplayBlock[]; +} + +/** Metadata written on tool messages so providers receive correct error semantics. */ +export interface ToolMessageMetadata { + isError?: boolean; +} + +/** Reserved Mutsumi metadata fields used by the LLM adapter. */ +export interface LlmMessageMetadata extends ToolMessageMetadata { + piAiReplay?: PiAiReplayState; +} diff --git a/src/mcp/tool.ts b/src/mcp/tool.ts index 97de51c..7a7b7a6 100644 --- a/src/mcp/tool.ts +++ b/src/mcp/tool.ts @@ -1,4 +1,4 @@ -import type OpenAI from "openai"; +import type { ToolDefinition } from "../tools.d/interface"; import type { Tool } from "@modelcontextprotocol/sdk/types.js"; import type { ITool, ToolContext } from "../tools.d/interface"; import type { McpToolCaller } from "./interfaces"; @@ -9,7 +9,7 @@ import { getMcpToolExposedName, getMcpToolSchemaError, projectMcpToolResult } fr export class McpToolAdapter implements ITool { readonly name: string; readonly shouldCache = false; - readonly definition: OpenAI.Chat.ChatCompletionTool; + readonly definition: ToolDefinition; readonly serverId: string; readonly originalToolName: string; diff --git a/src/notebook/commands/compressConversation.ts b/src/notebook/commands/compressConversation.ts index 7c65c11..53d37bb 100644 --- a/src/notebook/commands/compressConversation.ts +++ b/src/notebook/commands/compressConversation.ts @@ -11,7 +11,7 @@ import { createEmptyToolSet } from '../../tools.d/toolManager'; import type { AgentRunOptions } from '../../agent/types'; import { MutsumiSerializer } from '../serializer'; import { formatMessagesToString, createDebugSessionFromNotebook } from './utils'; -import { getCompressModelSelection, getModelCredentials, resolveModelSelection } from '../../utils'; +import { getCompressModelSelection, resolveModelSelection } from '../../utils'; import { t } from '../../i18n'; /** @@ -76,15 +76,6 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon const compressModel = compressSelection.model; const compressProvider = compressSelection.provider; - let credentials: { apiKey: string; baseUrl: string }; - try { - credentials = getModelCredentials(compressModel, compressProvider); - } catch (err: any) { - vscode.window.showErrorMessage(t('compress.failed', err.message)); - return; - } - const { apiKey, baseUrl } = credentials; - // Build session and get full interaction history const session = await createDebugSessionFromNotebook(editor.notebook, lastCodeCellIndex); const { messages } = await buildInteractionHistory(session); @@ -130,8 +121,6 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon const adapter = new LiteAdapter(); const compressConfig: LiteAgentSessionConfig = { model: compressModel, - apiKey, - baseUrl, metadata: editor.notebook.metadata ? JSON.parse(JSON.stringify(editor.notebook.metadata)) as AgentMetadata : undefined @@ -146,8 +135,7 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon // Create agent runner const runOptions: AgentRunOptions = { model: compressModel, - apiKey, - baseUrl, + provider: compressProvider, maxLoops: 1 // Single round since no tools }; const runner = new AgentRunner(runOptions, emptyToolSet, compressSession); diff --git a/src/notebook/commands/index.ts b/src/notebook/commands/index.ts index 7541849..68afca6 100644 --- a/src/notebook/commands/index.ts +++ b/src/notebook/commands/index.ts @@ -9,4 +9,5 @@ export { registerDebugContextCommand } from './debugContext'; export { registerToggleAutoApproveCommands } from './toggleAutoApprove'; export { registerTestRagSearchCommand } from './testRagSearch'; export { registerCompressConversationCommand } from './compressConversation'; +export { registerManageProvidersCommand } from './manageProviders'; export { registerPruneGhostBlocksCommand } from './pruneGhostBlocks'; diff --git a/src/notebook/commands/manageProviders.ts b/src/notebook/commands/manageProviders.ts new file mode 100644 index 0000000..5d01f8d --- /dev/null +++ b/src/notebook/commands/manageProviders.ts @@ -0,0 +1,218 @@ +import * as vscode from 'vscode'; +import type { AuthEvent, AuthInteraction, AuthPrompt } from '@earendil-works/pi-ai'; +import { LlmProviderService } from '../../llm/providerService'; +import type { CustomProviderProfile, ProviderInfo } from '../../llm/types'; +import { t } from '../../i18n'; + +interface ProviderPick extends vscode.QuickPickItem { + provider?: ProviderInfo; + action?: 'add'; +} + +function cancelled(): never { + throw new vscode.CancellationError(); +} + +function createInteraction(): AuthInteraction { + return { + async prompt(prompt: AuthPrompt): Promise { + if (prompt.signal?.aborted) cancelled(); + if (prompt.type === 'select') { + const selected = await vscode.window.showQuickPick( + prompt.options.map(option => ({ + label: option.label, + description: option.description, + value: option.id, + })), + { placeHolder: prompt.message }, + ); + return selected?.value ?? cancelled(); + } + const value = await vscode.window.showInputBox({ + title: prompt.message, + prompt: prompt.message, + placeHolder: prompt.placeholder, + password: prompt.type === 'secret', + ignoreFocusOut: true, + }); + return value ?? cancelled(); + }, + notify(event: AuthEvent): void { + if (event.type === 'auth_url') { + void vscode.env.openExternal(vscode.Uri.parse(event.url)); + } else if (event.type === 'device_code') { + void vscode.env.clipboard.writeText(event.userCode); + void vscode.env.openExternal(vscode.Uri.parse(event.verificationUri)); + void vscode.window.showInformationMessage(t('providers.deviceCode', event.userCode)); + } else { + void vscode.window.showInformationMessage(event.message); + } + }, + }; +} + +async function updateCustomProvider(id: string, existing?: CustomProviderProfile): Promise { + const displayName = await vscode.window.showInputBox({ + title: t('providers.displayName'), + value: existing?.displayName ?? id, + ignoreFocusOut: true, + }); + if (displayName === undefined) return false; + const baseUrl = await vscode.window.showInputBox({ + title: t('providers.baseUrl'), + value: existing?.baseUrl ?? 'http://localhost:8080/v1', + validateInput: value => { + try { + const url = new URL(value); + return url.protocol === 'http:' || url.protocol === 'https:' ? undefined : t('providers.httpUrl'); + } catch { + return t('providers.validUrl'); + } + }, + ignoreFocusOut: true, + }); + if (!baseUrl) return false; + const api = await vscode.window.showQuickPick([ + { label: t('providers.openaiCompletions'), value: 'openai-completions' as const }, + { label: t('providers.openaiResponses'), value: 'openai-responses' as const }, + ], { placeHolder: t('providers.protocol') }); + if (!api) return false; + const auth = await vscode.window.showQuickPick([ + { label: 'API Key', value: 'apiKey' as const }, + { label: t('providers.noAuth'), value: 'none' as const }, + ], { placeHolder: t('providers.authentication') }); + if (!auth) return false; + const manualModels = await vscode.window.showInputBox({ + title: t('providers.manualModels'), + prompt: t('providers.manualModelsPrompt'), + value: (existing?.models ?? []).join(', '), + ignoreFocusOut: true, + }); + if (manualModels === undefined) return false; + + const config = vscode.workspace.getConfiguration('mutsumi'); + const profiles = config.get>('customProviders', {}); + await config.update('customProviders', { + ...profiles, + [id]: { + displayName: displayName.trim() || id, + baseUrl: baseUrl.trim(), + api: api.value, + auth: auth.value, + models: [...new Set(manualModels.split(',').map(model => model.trim()).filter(Boolean))], + }, + }, vscode.ConfigurationTarget.Global); + const service = LlmProviderService.getInstance(); + await service.reload(); + if (auth.value === 'apiKey') { + const error = await service.configureApiKey(id, createInteraction()); + if (error) void vscode.window.showWarningMessage(t('providers.savedDiscoveryFailed', error.message)); + } else { + if (existing && (existing.auth ?? 'apiKey') === 'apiKey') await service.deleteCredential(id); + const errors = await service.refreshModels(); + if (errors.has(id)) void vscode.window.showWarningMessage(t('providers.savedDiscoveryFailed', errors.get(id)?.message ?? '')); + } + return true; +} + +async function addCustomProvider(): Promise { + const service = LlmProviderService.getInstance(); + const existingIds = new Set((await service.listProviders()).map(provider => provider.id)); + const id = await vscode.window.showInputBox({ + title: t('providers.routeId'), + prompt: t('providers.routeIdPrompt'), + validateInput: value => !value.trim() + ? t('providers.routeIdRequired') + : existingIds.has(value.trim()) ? t('providers.routeIdExists') : undefined, + ignoreFocusOut: true, + }); + if (!id) return; + if (await updateCustomProvider(id.trim())) { + void vscode.window.showInformationMessage(t('providers.added', id.trim())); + } +} + +async function removeCustomProvider(provider: ProviderInfo): Promise { + const confirmation = await vscode.window.showWarningMessage( + t('providers.removeConfirm', provider.name), + { modal: true }, + t('providers.remove'), + ); + if (confirmation !== t('providers.remove')) return; + const config = vscode.workspace.getConfiguration('mutsumi'); + const profiles = { ...config.get>('customProviders', {}) }; + delete profiles[provider.id]; + await config.update('customProviders', profiles, vscode.ConfigurationTarget.Global); + const service = LlmProviderService.getInstance(); + await service.deleteCredential(provider.id); + await service.deleteCachedModels(provider.id); + await service.reload(); +} + +async function manageProvider(provider: ProviderInfo): Promise { + const service = LlmProviderService.getInstance(); + const actions: Array = [ + { label: `$(refresh) ${t('providers.refresh')}`, value: 'refresh' }, + ]; + if (provider.canConfigureApiKey) actions.unshift( + { label: `$(key) ${t('providers.configureKey')}`, value: 'credential' }, + { label: `$(sign-out) ${t('providers.removeCredential')}`, value: 'logout' }, + ); + if (provider.isCustom) actions.push( + { label: `$(edit) ${t('providers.edit')}`, value: 'edit' }, + { label: `$(trash) ${t('providers.removeCustom')}`, value: 'remove' }, + ); + const selected = await vscode.window.showQuickPick(actions, { + title: provider.name, + placeHolder: provider.authSource ? t('providers.authenticatedBy', provider.authSource) : t('providers.notConfigured'), + }); + if (!selected) return; + if (selected.value === 'credential') { + const error = await service.configureApiKey(provider.id, createInteraction()); + void vscode.window.showInformationMessage(t('providers.credentialStored', provider.name)); + if (error) void vscode.window.showWarningMessage(t('providers.savedDiscoveryFailed', error.message)); + } else if (selected.value === 'logout') { + await service.deleteCredential(provider.id); + void vscode.window.showInformationMessage(t('providers.credentialRemoved', provider.name)); + } else if (selected.value === 'refresh') { + const errors = await service.refreshModels(); + const error = errors.get(provider.id); + if (error) throw error; + void vscode.window.showInformationMessage(t('providers.refreshed', provider.name)); + } else if (selected.value === 'edit') { + const profile = vscode.workspace.getConfiguration('mutsumi') + .get>('customProviders', {})[provider.id]; + await updateCustomProvider(provider.id, profile); + } else if (selected.value === 'remove') { + await removeCustomProvider(provider); + } +} + +/** Register provider management backed by SecretStorage and pi-ai catalogs. */ +export function registerManageProvidersCommand(context: vscode.ExtensionContext): void { + context.subscriptions.push(vscode.commands.registerCommand('mutsumi.manageProviders', async () => { + try { + const providers = await LlmProviderService.getInstance().listProviders(); + const picks: ProviderPick[] = providers.map(provider => ({ + label: provider.configured ? `$(pass-filled) ${provider.name}` : `$(circle-outline) ${provider.name}`, + description: provider.id, + detail: provider.authSource + ? t('providers.modelCountSource', provider.modelCount, provider.authSource) + : t('providers.modelCountUnconfigured', provider.modelCount), + provider, + })); + picks.unshift({ label: `$(add) ${t('providers.addCustom')}`, action: 'add' }); + const selected = await vscode.window.showQuickPick(picks, { + title: t('providers.title'), + placeHolder: t('providers.choose'), + matchOnDescription: true, + matchOnDetail: true, + }); + if (selected?.action === 'add') await addCustomProvider(); + else if (selected?.provider) await manageProvider(selected.provider); + } catch (error: any) { + if (error instanceof vscode.CancellationError) return; + void vscode.window.showErrorMessage(t('providers.failed', error.message ?? String(error))); + } + })); +} diff --git a/src/notebook/commands/selectModel.ts b/src/notebook/commands/selectModel.ts index 701803b..b6f8f9c 100644 --- a/src/notebook/commands/selectModel.ts +++ b/src/notebook/commands/selectModel.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import { normalizeReasoningEffort, REASONING_EFFORT_SETTING_VALUES } from '../../agent/types'; import type { ReasoningEffortSetting } from '../../agent/types'; -import { getModelsConfig } from '../../utils'; +import { LlmProviderService } from '../../llm/providerService'; import { t } from '../../i18n'; /** QuickPick item representing a configured model. */ @@ -59,8 +59,23 @@ export function registerSelectModelCommand(context: vscode.ExtensionContext): vo return; } - const modelsConfig = getModelsConfig(); - const providerEntries = Object.entries(modelsConfig); + const providerService = LlmProviderService.getInstance(); + let availableModels: Awaited>; + try { + availableModels = await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: t('selectModel.loading'), + }, () => providerService.listAvailableModels()); + } catch (error: any) { + vscode.window.showErrorMessage(t('selectModel.loadFailed', error.message)); + return; + } + const providerEntries = new Map(); + for (const model of availableModels) { + const entries = providerEntries.get(model.provider) ?? []; + entries.push(model); + providerEntries.set(model.provider, entries); + } const currentModel = editor.notebook.metadata?.model; const currentProvider = editor.notebook.metadata?.provider; @@ -70,8 +85,8 @@ export function registerSelectModelCommand(context: vscode.ExtensionContext): vo const modelItems: SelectModelQuickPickItem[] = []; let legacyMatched = false; - for (const [providerName, modelNames] of providerEntries) { - if (!Array.isArray(modelNames) || modelNames.length === 0) { + for (const [providerName, providerModels] of providerEntries) { + if (providerModels.length === 0) { continue; } modelItems.push({ @@ -79,7 +94,8 @@ export function registerSelectModelCommand(context: vscode.ExtensionContext): vo label: providerName, kind: vscode.QuickPickItemKind.Separator }); - for (const modelName of modelNames) { + for (const modelInfo of providerModels) { + const modelName = modelInfo.id; // When provider is stored in metadata, match on both model and provider. // For legacy notebooks without a provider field, fall back to // first-occurrence match on model name only. @@ -98,6 +114,7 @@ export function registerSelectModelCommand(context: vscode.ExtensionContext): vo value: modelName, provider: providerName, label: modelName, + description: modelInfo.name === modelName ? undefined : modelInfo.name, detail, picked: isCurrent }); @@ -105,11 +122,27 @@ export function registerSelectModelCommand(context: vscode.ExtensionContext): vo } if (modelItems.length === 0) { - vscode.window.showErrorMessage(t('selectModel.noModels')); + const manage = t('selectModel.manageProviders'); + const action = await vscode.window.showWarningMessage(t('selectModel.noModels'), manage); + if (action === manage) await vscode.commands.executeCommand('mutsumi.manageProviders'); return; } - const effortItems: ReasoningEffortQuickPickItem[] = REASONING_EFFORT_SETTING_VALUES.map(value => ({ + let supportedEfforts: readonly string[] = []; + if (currentModel && currentProvider) { + try { + supportedEfforts = providerService.resolveSelection({ + model: currentModel, + provider: currentProvider, + }).modelInfo.reasoningEfforts; + } catch { + supportedEfforts = []; + } + } + const effortValues = REASONING_EFFORT_SETTING_VALUES.filter( + value => value === 'default' || supportedEfforts.includes(value) + ); + const effortItems: ReasoningEffortQuickPickItem[] = effortValues.map(value => ({ itemType: 'reasoningEffort', value, label: value === 'default' ? t('selectModel.effortDefault') : value, diff --git a/src/notebook/toolbar.ts b/src/notebook/toolbar.ts index 58e8cf7..2330ab6 100644 --- a/src/notebook/toolbar.ts +++ b/src/notebook/toolbar.ts @@ -11,6 +11,7 @@ import { registerToggleAutoApproveCommands, registerTestRagSearchCommand, registerCompressConversationCommand, + registerManageProvidersCommand, registerPruneGhostBlocksCommand } from './commands'; @@ -25,5 +26,6 @@ export function registerToolbarCommands(context: vscode.ExtensionContext): void registerToggleAutoApproveCommands(context); registerTestRagSearchCommand(context); registerCompressConversationCommand(context); + registerManageProvidersCommand(context); registerPruneGhostBlocksCommand(context); } diff --git a/src/tools.d/interface.ts b/src/tools.d/interface.ts index c19b841..b485b03 100644 --- a/src/tools.d/interface.ts +++ b/src/tools.d/interface.ts @@ -1,5 +1,4 @@ import type * as vscode from 'vscode'; -import type OpenAI from 'openai'; import type { IAgentSession } from '../adapters/interfaces'; import type { ToolSession } from './toolSession'; @@ -23,9 +22,19 @@ export interface ToolContext { signalTermination: (isTaskComplete?: boolean) => void; } +/** Provider-neutral function tool schema accepted by pi-ai and MCP adapters. */ +export interface ToolDefinition { + type: 'function'; + function: { + name: string; + description?: string; + parameters?: Record; + }; +} + export interface ITool { name: string; - definition: OpenAI.Chat.ChatCompletionTool; + definition: ToolDefinition; execute(args: any, context: ToolContext): Promise; /** * Generate a human-readable description of the tool call. diff --git a/src/tools.d/toolManager.ts b/src/tools.d/toolManager.ts index 0c5c9fb..3ee6fc6 100644 --- a/src/tools.d/toolManager.ts +++ b/src/tools.d/toolManager.ts @@ -3,7 +3,7 @@ * @module toolManager */ -import type { ITool, ToolContext } from "./interface"; +import type { ITool, ToolContext, ToolDefinition } from "./interface"; import { readFileTool } from "./tools/read"; import { globTool } from "./tools/glob"; import { grepTool } from "./tools/grep"; @@ -29,7 +29,6 @@ import { queryCodebaseTool } from "./tools/rag"; import { AgentTypeRegistry } from "../registry/agentTypeRegistry"; import { ToolSetRegistry } from "../registry/toolSetRegistry"; import * as vscode from "vscode"; -import type OpenAI from "openai"; import { getCachedResult, setCachedResult } from "./cache"; import { McpRegistry } from "../mcp/registry"; import { McpToolAdapter } from "../mcp/tool"; @@ -97,10 +96,9 @@ export class ToolSet { } /** - * Gets all tool definitions formatted for OpenAI API. - * @returns {OpenAI.Chat.ChatCompletionTool[]} Array of tool definitions + * Gets provider-neutral function tool definitions. */ - getDefinitions(): OpenAI.Chat.ChatCompletionTool[] { + getDefinitions(): ToolDefinition[] { return Array.from(this.tools.values()).map((t) => t.definition); } @@ -419,13 +417,12 @@ export class ToolManager { } /** - * Gets tool definitions formatted for OpenAI API. + * Gets provider-neutral function tool definitions. * @param {boolean} isSubAgent - True for non-root/child sessions (includes task_finish) - * @returns {OpenAI.Chat.ChatCompletionTool[]} Array of tool definitions */ public getToolsDefinitions( isSubAgent: boolean, - ): OpenAI.Chat.ChatCompletionTool[] { + ): ToolDefinition[] { return this.getUserToolSet(isSubAgent).getDefinitions(); } diff --git a/src/types.ts b/src/types.ts index d73e89d..372ec63 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,19 +3,6 @@ * @module types */ -/** - * Provider configuration using snake_case for settings schema alignment. - * @interface Provider - */ -export interface Provider { - /** Provider name identifier */ - name: string; - /** Base URL for the provider's API */ - baseurl: string; - /** API key for the provider */ - api_key: string; -} - /** * Explicit model + provider pair. Used throughout settings, configuration, * persistence, and execution to avoid ambiguous first-match resolution. @@ -31,25 +18,12 @@ export interface ModelSelection { /** * Default providers used when user hasn't configured any providers. */ -export const DEFAULT_PROVIDERS: Provider[] = [ - { name: "kimi-for-coding", baseurl: "https://api.kimi.com/coding/v1", api_key: "" } -]; - -/** - * Default models configuration used when user hasn't configured any models. - * Keys are provider names, values are arrays of model identifiers supported - * by that provider. - */ -export const DEFAULT_MODELS: Record = { - "kimi-for-coding": ["kimi-for-coding"] -}; - /** * Built-in default model selection pair. */ export const DEFAULT_MODEL_SELECTION: ModelSelection = { model: "kimi-for-coding", - provider: "kimi-for-coding" + provider: "kimi-coding" }; /** @@ -135,8 +109,8 @@ export interface AgentMessage { name?: string; /** Reasoning/thinking content from the model */ reasoning_content?: string; - /** Additional metadata for the message (e.g. ghost block state) */ - metadata?: any; + /** Additional durable metadata, including versioned pi-ai replay state and ghost blocks. */ + metadata?: import('./llm/types').LlmMessageMetadata & Record; } /** diff --git a/src/utils.ts b/src/utils.ts index a2d3e6b..706959c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,12 +7,10 @@ import * as vscode from 'vscode'; import * as path from 'path'; import * as fs from 'fs'; import { - Provider, ModelSelection, - DEFAULT_PROVIDERS, - DEFAULT_MODELS, DEFAULT_MODEL_SELECTION } from './types'; +import { LlmProviderService } from './llm/providerService'; /** * Resolved model selection: the canonical { model, provider } pair plus the @@ -20,8 +18,8 @@ import { * @interface ResolvedModelSelection */ export interface ResolvedModelSelection extends ModelSelection { - /** The provider entry that matched the canonical provider name */ - providerEntry: Provider; + /** Resolved model capability metadata */ + modelInfo: import('./llm/types').ModelInfo; } /** @@ -54,98 +52,7 @@ export function resolveModelSelection(selection: unknown): ResolvedModelSelectio throw new Error('Model selection "provider" must be a non-empty string'); } - const config = vscode.workspace.getConfiguration('mutsumi'); - let providers = config.get('providers', []); - const models = getModelsConfig(); - - if (providers.length === 0) { - providers = DEFAULT_PROVIDERS; - } - - // Check for duplicate provider names after trimming - const seenNames = new Set(); - for (const p of providers) { - const trimmedName = p.name.trim(); - if (seenNames.has(trimmedName)) { - throw new Error(`Duplicate provider name after normalization: "${trimmedName}"`); - } - seenNames.add(trimmedName); - } - - // Provider must exist by explicit name - const matchedProvider = providers.find(p => p.name.trim() === provider); - if (!matchedProvider) { - throw new Error(`Provider "${provider}" not found`); - } - - // Provider must declare the requested model - let providerDeclaresModel = false; - for (const [pName, modelList] of Object.entries(models)) { - if (pName.trim() === provider && Array.isArray(modelList) && modelList.includes(model)) { - providerDeclaresModel = true; - break; - } - } - if (!providerDeclaresModel) { - throw new Error(`Model "${model}" is not declared by provider "${provider}"`); - } - - return { model, provider, providerEntry: matchedProvider }; -} - -/** - * Gets the provider credentials for a given model/provider pair. - * @description Resolves and validates the pair through resolveModelSelection, - * then reads the API key and base URL from the matched provider entry returned - * by that single lookup. Provider is required; no first-match fallback is - * performed. - * @param {string} modelName - The model identifier - * @param {string} providerName - The provider name (required) - * @returns {{ apiKey: string; baseUrl: string }} Provider credentials with camelCase property names - * @throws {Error} If provider not found, model not declared, or required fields are empty - */ -export function getModelCredentials(modelName: string, providerName: string): { apiKey: string; baseUrl: string } { - const { provider, providerEntry } = resolveModelSelection({ model: modelName, provider: providerName }); - - const baseUrl = providerEntry.baseurl.trim(); - if (!baseUrl) { - throw new Error(`Provider "${provider}" has empty baseurl`); - } - - const apiKey = providerEntry.api_key; - if (!apiKey) { - throw new Error(`Provider "${provider}" has empty api_key`); - } - - return { apiKey, baseUrl }; -} - -/** - * Gets the models configuration from VS Code settings. - * @description Returns user-configured models if available, otherwise returns - * the built-in default models. The configuration maps provider names to arrays - * of model identifiers supported by that provider. - * @returns {Record} Models configuration (provider name -> model identifiers) - */ -export function getModelsConfig(): Record { - const config = vscode.workspace.getConfiguration('mutsumi'); - const models = config.get>('models', {}); - - if (Object.keys(models).length > 0) { - return models; - } - - return DEFAULT_MODELS; -} - -/** - * Gets the list of all available model names from the models configuration. - * @description Flattens the provider-to-models mapping and returns unique model names. - * @returns {string[]} Array of unique model names - */ -export function getAvailableModelNames(): string[] { - const models = getModelsConfig(); - return [...new Set(Object.values(models).flat())]; + return LlmProviderService.getInstance().resolveSelection({ model, provider }); } /** diff --git a/tests/credentialStore.test.ts b/tests/credentialStore.test.ts new file mode 100644 index 0000000..7c94a89 --- /dev/null +++ b/tests/credentialStore.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, it } from 'vitest'; +import { VsCodeCredentialStore } from '../src/llm/credentialStore'; + +class MemorySecrets { + readonly values = new Map(); + async get(key: string) { return this.values.get(key); } + async store(key: string, value: string) { this.values.set(key, value); } + async delete(key: string) { this.values.delete(key); } +} + +class MemoryMemento { + readonly values = new Map(); + get(key: string, fallback?: T): T { return (this.values.has(key) ? this.values.get(key) : fallback) as T; } + async update(key: string, value: unknown) { this.values.set(key, value); } +} + +describe('VsCodeCredentialStore', () => { + it('stores full credentials only in SecretStorage and lists metadata without secrets', async () => { + const secrets = new MemorySecrets(); + const state = new MemoryMemento(); + const store = new VsCodeCredentialStore(secrets as any, state as any); + + await store.storeApiKey('anthropic', 'secret-value'); + + expect(await store.read('anthropic')).toEqual({ type: 'api_key', key: 'secret-value' }); + expect(await store.list()).toEqual([{ providerId: 'anthropic', type: 'api_key' }]); + expect(JSON.stringify([...state.values])).not.toContain('secret-value'); + expect([...secrets.values.values()][0]).toContain('secret-value'); + }); + + it('serializes concurrent writes for the same provider and deletes the index entry', async () => { + const secrets = new MemorySecrets(); + const state = new MemoryMemento(); + const store = new VsCodeCredentialStore(secrets as any, state as any); + await store.storeApiKey('openai', 'first'); + + await Promise.all([ + store.modify('openai', async current => ({ ...current!, key: `${(current as any).key}-second` })), + store.modify('openai', async current => ({ ...current!, key: `${(current as any).key}-third` })), + ]); + + expect((await store.read('openai') as any).key).toBe('first-second-third'); + await store.delete('openai'); + expect(await store.read('openai')).toBeUndefined(); + expect(await store.list()).toEqual([]); + }); +}); diff --git a/tests/llmClient.test.ts b/tests/llmClient.test.ts new file mode 100644 index 0000000..a3a4829 --- /dev/null +++ b/tests/llmClient.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, it, vi } from 'vitest'; +import type { Api, AssistantMessage } from '@earendil-works/pi-ai'; + +const state = vi.hoisted(() => ({ api: 'openai-completions' as Api, captured: undefined as any })); +vi.mock('../src/llm/providerService', () => ({ + LlmProviderService: { + getInstance: () => ({ + prepare: (provider: string, model: string) => ({ + model: { provider, id: model }, + models: { + streamSimple: (_model: unknown, context: unknown, options: unknown) => { + state.captured = { context, options }; + const message: AssistantMessage = { + role: 'assistant', api: state.api, provider, model, + stopReason: 'toolUse', timestamp: 1, + usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0, totalTokens: 2, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } }, + content: [{ type: 'toolCall', id: 'call-1', name: 'read', arguments: { path: 'file.ts' } }], + }; + return (async function* () { + // Some protocols only expose complete arguments at toolcall_end. + yield { type: 'toolcall_end', contentIndex: 0, toolCall: message.content[0], partial: message } as any; + yield { type: 'done', reason: 'toolUse', message } as any; + })(); + }, + }, + }), + }), + }, +})); + +import { LLMClient } from '../src/agent/llmClient'; + +describe.each([ + ['OpenAI', 'openai-completions'], + ['Anthropic', 'anthropic-messages'], + ['Google', 'google-generative-ai'], +] as const)('%s protocol adapter', (_label, api) => { + it('completes a provider-neutral streamed tool-call round without a real credential', async () => { + state.api = api; + const client = new LLMClient({ provider: `mock-${api}`, model: 'model', reasoningEffort: 'none' }); + const chunks = []; + for await (const chunk of client.streamChatCompletion({ + messages: [{ role: 'system', content: 'rules' }, { role: 'user', content: 'read it' }], + tools: [{ type: 'function', function: { name: 'read', parameters: { type: 'object' } } }], + })) chunks.push(chunk); + + expect(chunks[0].tool_calls?.[0]).toMatchObject({ + id: 'call-1', function: { name: 'read', arguments: '{"path":"file.ts"}' }, + }); + expect(chunks.at(-1)?.replayState).toMatchObject({ api, provider: `mock-${api}`, stopReason: 'toolUse' }); + expect(state.captured.context).toMatchObject({ systemPrompt: 'rules', tools: [{ name: 'read' }] }); + expect(state.captured.options).toMatchObject({ maxRetries: 0 }); + expect(state.captured.options).toMatchObject({ reasoning: 'off' }); + }); +}); diff --git a/tests/migration.test.ts b/tests/migration.test.ts new file mode 100644 index 0000000..4cc055d --- /dev/null +++ b/tests/migration.test.ts @@ -0,0 +1,113 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +type Values = Record; +const state = vi.hoisted(() => ({ + global: {} as Values, + workspace: {} as Values, + folders: new Map(), + updates: [] as Array<{ resource?: string; key: string; value: unknown; target: number }>, + fail: undefined as undefined | ((resource: string | undefined, key: string, value: unknown, target: number) => boolean), + storeApiKey: vi.fn(), + reload: vi.fn(), + builtInRoutes: new Set(['kimi-coding']), +})); + +vi.mock('vscode', () => { + const ConfigurationTarget = { Global: 1, Workspace: 2, WorkspaceFolder: 3 }; + const getValues = (resource?: { path: string }) => resource ? state.folders.get(resource.path) ?? {} : {}; + return { + ConfigurationTarget, + workspace: { + workspaceFolders: [{ uri: { path: '/one' } }, { uri: { path: '/two' } }], + getConfiguration: (_section: string, resource?: { path: string }) => ({ + inspect: (key: string) => ({ + globalValue: state.global[key], + workspaceValue: state.workspace[key], + workspaceFolderValue: getValues(resource)[key], + }), + update: async (key: string, value: unknown, target: number) => { + const resourcePath = resource?.path; + state.updates.push({ resource: resourcePath, key, value, target }); + if (state.fail?.(resourcePath, key, value, target)) throw new Error('write failed'); + const values = target === 1 ? state.global : target === 2 ? state.workspace : getValues(resource); + if (value === undefined) delete values[key]; else values[key] = value; + }, + }), + }, + window: { showWarningMessage: vi.fn(), showInformationMessage: vi.fn(), showErrorMessage: vi.fn() }, + commands: { registerCommand: vi.fn(() => ({ dispose() {} })) }, + l10n: { t: (key: string, ...args: unknown[]) => `${key}${args.length ? `: ${args.join(', ')}` : ''}` }, + }; +}); + +vi.mock('../src/llm/providerService', () => ({ + LlmProviderService: { + getInstance: () => ({ + getCredentialStore: () => ({ storeApiKey: state.storeApiKey }), + reload: state.reload, + isBuiltInProviderId: (id: string) => state.builtInRoutes.has(id), + }), + }, +})); + +import { migrateLegacyProviders } from '../src/llm/migration'; + +const legacy = (name: string, key: string, baseurl = 'https://example.test/v1') => ({ name, baseurl, api_key: key }); + +beforeEach(() => { + state.global = {}; + state.workspace = {}; + state.folders = new Map([['/one', {}], ['/two', {}]]); + state.updates = []; + state.fail = undefined; + state.storeApiKey.mockReset().mockResolvedValue(undefined); + state.reload.mockReset().mockResolvedValue(undefined); + state.builtInRoutes = new Set(['kimi-coding']); +}); + +describe('legacy provider migration', () => { + it('stops before writes when one route has conflicting plaintext keys across scopes', async () => { + state.global.providers = [legacy('shared', 'one')]; + state.folders.get('/two')!.providers = [legacy('shared', 'two')]; + await expect(migrateLegacyProviders()).rejects.toThrow('migration.conflicts'); + expect(state.storeApiKey).not.toHaveBeenCalled(); + expect(state.updates).toEqual([]); + }); + + it('requires legacy custom routes that collide with built-ins to be renamed', async () => { + state.global.providers = [legacy('kimi-coding', 'key', 'https://proxy.example.test/v1')]; + await expect(migrateLegacyProviders()).rejects.toThrow('migration.routeConflicts'); + expect(state.storeApiKey).not.toHaveBeenCalled(); + }); + + it('migrates all scopes, aliases exact Kimi defaults, and removes plaintext only after secure writes', async () => { + state.global.providers = [legacy('kimi-for-coding', 'kimi-key', 'https://api.kimi.com/coding/v1')]; + state.workspace.providers = [legacy('proxy', 'proxy-key')]; + state.workspace.models = { proxy: ['model-a'] }; + state.folders.get('/one')!.providers = [legacy('folder-route', 'folder-key')]; + + await expect(migrateLegacyProviders()).resolves.toBe(true); + + expect(state.storeApiKey.mock.calls).toEqual([ + ['kimi-coding', 'kimi-key'], ['proxy', 'proxy-key'], ['folder-route', 'folder-key'], + ]); + expect((state.workspace.customProviders as any).proxy).toMatchObject({ models: ['model-a'], auth: 'apiKey' }); + expect(state.global.providers).toBeUndefined(); + expect(state.workspace.providers).toBeUndefined(); + expect(state.folders.get('/one')!.providers).toBeUndefined(); + const firstCleanup = state.updates.findIndex(update => update.key === 'providers' && update.value === undefined); + const lastCustom = state.updates.reduce((last, update, index) => update.key === 'customProviders' ? index : last, -1); + expect(firstCleanup).toBeGreaterThan(lastCustom); + }); + + it('restores already-cleared plaintext settings if cleanup fails midway', async () => { + state.global.providers = [legacy('global', 'one')]; + state.workspace.providers = [legacy('workspace', 'two')]; + state.fail = (_resource, key, value, target) => key === 'models' && value === undefined && target === 2; + + await expect(migrateLegacyProviders()).rejects.toThrow('write failed'); + + expect(state.global.providers).toEqual([legacy('global', 'one')]); + expect(state.workspace.providers).toEqual([legacy('workspace', 'two')]); + }); +}); diff --git a/tests/providerService.test.ts b/tests/providerService.test.ts new file mode 100644 index 0000000..d4c203f --- /dev/null +++ b/tests/providerService.test.ts @@ -0,0 +1,161 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; + +const vscodeState = vi.hoisted(() => ({ profiles: {} as Record })); +vi.mock('vscode', () => ({ + workspace: { + getConfiguration: () => ({ get: (_key: string, fallback: unknown) => vscodeState.profiles ?? fallback }), + }, +})); + +import { LlmProviderService } from '../src/llm/providerService'; + +class MemorySecrets { + readonly values = new Map(); + async get(key: string) { return this.values.get(key); } + async store(key: string, value: string) { this.values.set(key, value); } + async delete(key: string) { this.values.delete(key); } +} + +class MemoryMemento { + readonly values = new Map(); + get(key: string, fallback?: T): T { return (this.values.has(key) ? this.values.get(key) : fallback) as T; } + async update(key: string, value: unknown) { this.values.set(key, value); } +} + +function context() { + return { secrets: new MemorySecrets(), globalState: new MemoryMemento() } as any; +} + +afterEach(() => { + vscodeState.profiles = {}; + vi.restoreAllMocks(); + vi.useRealTimers(); +}); + +describe('LlmProviderService registry', () => { + it('loads the built-in catalog and preserves the legacy Kimi alias', async () => { + const service = new LlmProviderService(); + await service.initialize(context()); + const selection = service.resolveSelection({ provider: 'kimi-for-coding', model: 'kimi-for-coding' }); + expect(selection.provider).toBe('kimi-coding'); + expect(selection.modelInfo.input).toContain('image'); + }); + + it('rejects custom route collisions without replacing the previous registry', async () => { + const service = new LlmProviderService(); + await service.initialize(context()); + vscodeState.profiles = { + 'kimi-coding': { baseUrl: 'https://example.test/v1', auth: 'none' }, + }; + + await expect(service.reload()).rejects.toThrow('conflicts with a built-in provider'); + expect(service.getModel('kimi-coding', 'kimi-for-coding').id).toBe('kimi-for-coding'); + }); + + it.each([ + [{ 'kimi-for-coding': { baseUrl: 'https://example.test/v1' } }, 'conflicts with a built-in provider'], + [{ local: { baseUrl: 'file:///tmp/models' } }, 'must use HTTP(S)'], + [{ local: { baseUrl: 'https://user:secret@example.test/v1' } }, 'must not contain credentials'], + ])('rejects unsafe or conflicting custom configuration', async (profiles, message) => { + vscodeState.profiles = profiles; + const service = new LlmProviderService(); + await expect(service.initialize(context())).rejects.toThrow(message); + }); + + it('normalizes custom routes and applies conservative manual model defaults', async () => { + vscodeState.profiles = { + local: { + displayName: ' Local ', baseUrl: 'http://localhost:8080/v1/', + auth: 'none', models: [' test-model ', 'test-model'], + }, + }; + const service = new LlmProviderService(); + await service.initialize(context()); + const model = service.getModel('local', 'test-model'); + expect(model).toMatchObject({ contextWindow: 262144, maxTokens: 32768, input: ['text'] }); + }); + + it('uses built-in ambient environment credentials as a SecretStorage fallback', async () => { + const previous = process.env.OPENAI_API_KEY; + process.env.OPENAI_API_KEY = 'environment-secret'; + try { + const service = new LlmProviderService(); + await service.initialize(context()); + const openai = (await service.listProviders()).find(provider => provider.id === 'openai'); + expect(openai).toMatchObject({ configured: true }); + expect(JSON.stringify(openai)).not.toContain('environment-secret'); + } finally { + if (previous === undefined) delete process.env.OPENAI_API_KEY; + else process.env.OPENAI_API_KEY = previous; + } + }); +}); + +describe('custom /models discovery', () => { + it('uses Bearer auth and validates a successful OpenAI-shaped listing', async () => { + const service = new LlmProviderService(); + const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response(JSON.stringify({ + data: [{ id: 'remote-model', display_name: 'Remote', context_window: 8192, max_output_tokens: 2048 }], + }), { status: 200, headers: { 'content-type': 'application/json' } })); + + const models = await (service as any).discoverCustomModels( + 'custom', { baseUrl: 'https://example.test/v1', api: 'openai-completions' }, + { credential: { type: 'api_key', key: 'secret' } }, + ); + + expect(fetchMock).toHaveBeenCalledWith('https://example.test/v1/models', expect.objectContaining({ + headers: expect.objectContaining({ authorization: 'Bearer secret' }), + })); + expect(models[0]).toMatchObject({ id: 'remote-model', name: 'Remote', contextWindow: 8192, maxTokens: 2048 }); + }); + + it.each([ + ['invalid JSON', new Response('{', { status: 200 }), 'did not return JSON'], + ['authentication failure', new Response('', { status: 401 }), 'check the API key'], + ['oversized response', new Response('', { status: 200, headers: { 'content-length': String(4 * 1024 * 1024 + 1) } }), 'returned more than'], + ])('rejects %s without accepting a bad catalog', async (_name, response, expected) => { + const service = new LlmProviderService(); + vi.spyOn(globalThis, 'fetch').mockResolvedValue(response); + await expect((service as any).discoverCustomModels( + 'custom', { baseUrl: 'https://example.test/v1' }, { credential: undefined }, + )).rejects.toThrow(expected); + }); + + it('honors caller cancellation', async () => { + const service = new LlmProviderService(); + vi.spyOn(globalThis, 'fetch').mockImplementation((_url, init) => new Promise((_resolve, reject) => { + (init?.signal as AbortSignal).addEventListener('abort', () => reject(new DOMException('Aborted', 'AbortError'))); + })); + const controller = new AbortController(); + const pending = (service as any).discoverCustomModels( + 'custom', { baseUrl: 'https://example.test/v1' }, { signal: controller.signal }, + ); + controller.abort(); + await expect(pending).rejects.toMatchObject({ name: 'AbortError' }); + }); + + it('times out a stalled discovery request', async () => { + vi.useFakeTimers(); + const service = new LlmProviderService(); + vi.spyOn(globalThis, 'fetch').mockImplementation((_url, init) => new Promise((_resolve, reject) => { + (init?.signal as AbortSignal).addEventListener('abort', () => reject(new DOMException('Aborted', 'AbortError'))); + })); + const pending = expect((service as any).discoverCustomModels( + 'custom', { baseUrl: 'https://example.test/v1' }, { credential: undefined }, + )).rejects.toMatchObject({ name: 'AbortError' }); + await vi.advanceTimersByTimeAsync(15_000); + await pending; + }); + + it('retains the previous manual catalog when a refresh fails', async () => { + vscodeState.profiles = { + local: { baseUrl: 'https://example.test/v1', auth: 'none', models: ['fallback-model'] }, + }; + const service = new LlmProviderService(); + await service.initialize(context()); + vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response('', { status: 503 })); + const errors = await service.refreshModels(); + expect(errors.get('local')).toBeInstanceOf(Error); + expect(service.getModel('local', 'fallback-model').id).toBe('fallback-model'); + }); +}); diff --git a/tests/replayAndContext.test.ts b/tests/replayAndContext.test.ts new file mode 100644 index 0000000..61c60f3 --- /dev/null +++ b/tests/replayAndContext.test.ts @@ -0,0 +1,68 @@ +import { describe, expect, it } from 'vitest'; +import type { AssistantMessage } from '@earendil-works/pi-ai'; +import { toPiContext } from '../src/llm/context'; +import { toPiAssistant, toReplayState } from '../src/llm/replay'; +import type { AgentMessage } from '../src/types'; + +const native: AssistantMessage = { + role: 'assistant', api: 'anthropic-messages', provider: 'anthropic', model: 'claude-test', + stopReason: 'toolUse', timestamp: 1, + usage: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0, totalTokens: 3, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } }, + content: [ + { type: 'thinking', thinking: 'reason', thinkingSignature: 'signed-reason' }, + { type: 'text', text: 'hello', textSignature: 'signed-text' }, + { type: 'toolCall', id: 'call-1', name: 'read', arguments: { path: 'a.ts' }, thoughtSignature: 'signed-tool' }, + ], +}; + +describe('pi-ai replay state', () => { + it('round-trips signed native blocks when visible content still matches', () => { + const message: AgentMessage = { + role: 'assistant', content: 'hello', reasoning_content: 'reason', + tool_calls: [{ id: 'call-1', type: 'function', function: { name: 'read', arguments: '{"path":"a.ts"}' } }], + metadata: { piAiReplay: toReplayState(native) }, + }; + expect(toPiAssistant(message)).toMatchObject({ + api: 'anthropic-messages', provider: 'anthropic', model: 'claude-test', + content: [ + { type: 'thinking', thinkingSignature: 'signed-reason' }, + { type: 'text', textSignature: 'signed-text' }, + { type: 'toolCall', thoughtSignature: 'signed-tool' }, + ], + }); + }); + + it('drops signatures and treats edited or corrupt metadata as a foreign assistant', () => { + const message: AgentMessage = { + role: 'assistant', content: 'edited', reasoning_content: 'reason', + metadata: { piAiReplay: toReplayState(native) }, + }; + const converted = toPiAssistant(message); + expect(converted.api).toBe('mutsumi-foreign'); + expect(converted.content).toEqual([ + { type: 'thinking', thinking: 'reason' }, + { type: 'text', text: 'edited' }, + ]); + }); +}); + +describe('provider-neutral context conversion', () => { + it('converts system, image, tools, and tool error semantics', () => { + const context = toPiContext([ + { role: 'system', content: 'rules' }, + { role: 'user', content: [ + { type: 'text', text: 'look' }, + { type: 'image_url', image_url: { url: 'data:image/png;base64,AQID' } }, + ] }, + { role: 'tool', name: 'read', tool_call_id: 'call-1', content: 'Error: missing' }, + ], [{ type: 'function', function: { name: 'read', description: 'Read', parameters: { type: 'object' } } }]); + + expect(context.systemPrompt).toBe('rules'); + expect(context.messages[0]).toMatchObject({ role: 'user', content: [ + { type: 'text', text: 'look' }, + { type: 'image', mimeType: 'image/png', data: 'AQID' }, + ] }); + expect(context.messages[1]).toMatchObject({ role: 'toolResult', isError: true }); + expect(context.tools?.[0]).toMatchObject({ name: 'read', parameters: { type: 'object' } }); + }); +}); diff --git a/tests/tsconfig.json b/tests/tsconfig.json new file mode 100644 index 0000000..f4c116a --- /dev/null +++ b/tests/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": "..", + "noEmit": true, + "types": ["node", "vitest/globals"] + }, + "include": ["./**/*.ts"], + "exclude": [] +} diff --git a/tsconfig.json b/tsconfig.json index 27457eb..0592294 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,8 @@ "exclude": [ "node_modules", ".vscode-test", + "tests", + "vitest.config.ts", "src/notebook/renderer.ts" ] } diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..add6a82 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'node', + include: ['tests/**/*.test.ts'], + clearMocks: true, + }, +}); From 345a1d72c985da3098ef2162af61be1fd30c9707 Mon Sep 17 00:00:00 2001 From: Guilimao_Official <1137056144@qq.com> Date: Fri, 14 Aug 2026 18:02:51 +0800 Subject: [PATCH 2/3] fix(dev): bump @types/node to ^22 to satisfy vite 7 peer requirement vitest 3.2.7 pulls in vite 7 which requires @types/node >=20.19 (peer). The project pinned @types/node ^18 since the scaffolded init commit while the real runtime (electron 39) and CI both use node 22, so npm ci on a clean node 22 environment failed with 'Missing @types/node@26.2.0 from lock file'. Aligning the type target with the actual node version also resolves the lock/package.json sync error. --- package-lock.json | 27 ++++++--------------------- package.json | 2 +- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index e2b727a..2f43267 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@types/better-sqlite3": "^7.6.13", "@types/diff": "^8.0.0", "@types/express": "^5.0.6", - "@types/node": "^18.0.0", + "@types/node": "^22.0.0", "@types/node-notifier": "^8.0.5", "@types/uuid": "^9.0.8", "@types/vscode": "^1.108.1", @@ -2581,12 +2581,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "18.19.130", - "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "version": "22.20.1", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.21.0" } }, "node_modules/@types/node-notifier": { @@ -4307,21 +4307,6 @@ "dev": true, "license": "ISC" }, - "node_modules/electron/node_modules/@types/node": { - "version": "22.19.15", - "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/electron/node_modules/undici-types": { - "version": "6.21.0", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, "node_modules/emoji-regex": { "version": "8.0.0", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", @@ -10514,8 +10499,8 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.21.0", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index 6b91a20..78b7810 100644 --- a/package.json +++ b/package.json @@ -751,7 +751,7 @@ "@types/better-sqlite3": "^7.6.13", "@types/diff": "^8.0.0", "@types/express": "^5.0.6", - "@types/node": "^18.0.0", + "@types/node": "^22.0.0", "@types/node-notifier": "^8.0.5", "@types/uuid": "^9.0.8", "@types/vscode": "^1.108.1", From 090cd19d40969ba56a1409e7ad6689d68f5cf99b Mon Sep 17 00:00:00 2001 From: Guilimao_Official <1137056144@qq.com> Date: Fri, 21 Aug 2026 11:40:35 +0800 Subject: [PATCH 3/3] refactor(mtm): finalize format v1 and harden session persistence Adopt native pi-ai messages and explicit provider/model identities across notebook and headless sessions. Persist Markdown notes separately, support pending user turns, hydrate provider history safely, and eliminate duplicate HTTP prompts. --- AGENTS.md | 10 +- README.md | 4 +- README_zh.md | 4 +- docs/custom-renderer-target-state.md | 10 +- docs/mtm-format.md | 28 ++ docs/multi-provider-refactor.md | 169 +-------- docs/reasoning-effort-target-state.md | 4 +- l10n/bundle.l10n.json | 12 +- l10n/bundle.l10n.zh-cn.json | 12 +- package.json | 46 --- package.nls.json | 8 +- package.nls.zh-cn.json | 8 +- src/adapters/headlessAdapter.ts | 58 ++- src/adapters/interfaces.ts | 10 +- src/adapters/liteAdapter.ts | 12 +- src/adapters/notebookAdapter.ts | 78 ++--- src/agent/agentRunner.ts | 155 ++++---- src/agent/fileOps.ts | 36 +- src/agent/llmClient.ts | 141 ++------ src/agent/llmStream.ts | 302 +++------------- src/agent/titleGenerator.ts | 51 +-- src/agent/toolExecutor.ts | 31 +- src/agent/types.ts | 21 ++ src/agent/uiRenderer.ts | 8 +- src/contextManagement/history.ts | 164 ++++++--- src/contextManagement/templateEngine.ts | 9 +- src/contextManagement/utils.ts | 14 +- src/controller.ts | 20 +- src/extension.ts | 2 - src/httpServer/agent.ts | 16 +- src/httpServer/agents.ts | 3 +- src/httpServer/chat.ts | 123 ++++--- src/httpServer/rules.ts | 10 +- src/llm/context.ts | 82 +---- src/llm/credentialStore.ts | 2 +- src/llm/messageText.ts | 21 ++ src/llm/migration.ts | 165 --------- src/llm/providerService.ts | 45 +-- src/llm/replay.ts | 169 --------- src/llm/types.ts | 30 -- src/mtmFormat.ts | 235 +++++++++++++ src/notebook/commands/compressConversation.ts | 37 +- src/notebook/commands/selectModel.ts | 14 +- src/notebook/commands/utils.ts | 51 +-- src/notebook/serializer.ts | 331 ++++++++---------- src/types.ts | 135 +++++-- tests/agentRunnerStatus.test.ts | 201 +++++++++++ tests/llmClient.test.ts | 11 +- tests/migration.test.ts | 113 ------ tests/mtmFormat.test.ts | 215 ++++++++++++ tests/providerService.test.ts | 8 +- tests/replayAndContext.test.ts | 68 ---- 52 files changed, 1626 insertions(+), 1886 deletions(-) create mode 100644 docs/mtm-format.md create mode 100644 src/llm/messageText.ts delete mode 100644 src/llm/migration.ts delete mode 100644 src/llm/replay.ts create mode 100644 src/mtmFormat.ts create mode 100644 tests/agentRunnerStatus.test.ts delete mode 100644 tests/migration.test.ts create mode 100644 tests/mtmFormat.test.ts delete mode 100644 tests/replayAndContext.test.ts diff --git a/AGENTS.md b/AGENTS.md index 2629b08..4ad4b9f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,16 +37,16 @@ src/ ### 2.1 `.mtm` 文件模型与 Serializer(`notebook/serializer.ts`) -`.mtm` 是 JSON:`{ metadata: AgentMetadata, context: AgentMessage[] }`。VS Code 通过 `NotebookSerializer` 把它与 Notebook 文档互相转换。 +`.mtm` 是 JSON:`{ formatVersion: 1, metadata: AgentMetadata, context: PersistedAgentMessage[], notes?: NotebookNote[] }`。VS Code 通过 `NotebookSerializer` 把它与 Notebook 文档互相转换。 核心算法是 **messages ↔ generic cells 双向映射**(`messagesToGenericCells` / `genericCellsToMessages`),并被 HeadlessAdapter 复用,因此协议是"与 UI 无关"的: - User 消息 → Code cell(kind 2) -- Assistant 消息 → Markup cell(kind 1) +- Markup cell(kind 1)→ 用户注释,按 `notes.beforeUserIndex` 独立持久化,不进入 Agent 历史 - **紧随 user 的 assistant/tool 消息组不单独建 cell**,而是存入该 user cell 的 `mutsumi_interaction` metadata,渲染为该 cell 的输出区(这是最反直觉的点) -- System 消息 → 带 `**System**: ` 前缀的 Markup cell,反序列化时剥前缀 -- 孤儿 assistant/tool 消息(无前置 user)→ 直接拍平成 markdown 存 cell value,**不写** `mutsumi_interaction` -- `mutsumi_interaction` **只存在于 user cell**,永不写在 assistant cell 上 +- Assistant/tool 消息必须附着于前置 user;磁盘中不支持孤儿 assistant/tool 或 system 消息 +- `mutsumi_interaction` **只存在于 user cell**,永不写在 Markup cell 上 +- 连续 user 是合法 pending turns;只在 provider 边界临时合并,磁盘 Cell 边界保持不变 - cell value 中保存的幽灵块 markdown 在反序列化时剥离(`stripGhostBlockFromCell`),结构化版本在 metadata 中 序列化时 `sub_agents_list` 与 `AgentOrchestrator` 内存注册表**双向同步**(打开时注入 childIds,保存时回写)。 diff --git a/README.md b/README.md index baea662..7acfe61 100644 --- a/README.md +++ b/README.md @@ -283,7 +283,9 @@ Mutsumi defaults to the `kimi-for-coding` model on the built-in `kimi-coding` pr Keys are entered through a password input and stored in VS Code SecretStorage. They are never written to settings, `.mtm` files, model caches, or logs. The provider manager also supports non-secret custom OpenAI-compatible routes and `/models` discovery. -Existing `mutsumi.providers` / `mutsumi.models` configurations are migration-only. On upgrade, accept the secure migration prompt or run **Mutsumi: Migrate Legacy Provider Credentials** manually. Rotate any key previously committed to version control. +Mutsumi only accepts the current versioned `.mtm` format and current provider settings. Convert older files with the standalone migration project, then enter credentials again through **Mutsumi: Manage Model Providers**. + +The built-in **+ Markdown** button adds a user-only annotation. Its Markdown source and position are saved in the `.mtm` file, but the annotation is never sent to the model or included in conversation compression and title generation. > **Note:** This Agent framework is specifically designed and optimized around the Kimi base model family. Using `kimi-for-coding` is highly recommended. diff --git a/README_zh.md b/README_zh.md index 5d1a087..4ff9af1 100644 --- a/README_zh.md +++ b/README_zh.md @@ -283,7 +283,9 @@ Mutsumi 默认使用内置 `kimi-coding` 提供商的 `kimi-for-coding` 模型 密钥通过密码输入框录入并存入 VS Code SecretStorage,绝不会写入设置、`.mtm` 文件、模型缓存或日志。提供商管理器还支持不含秘密的自定义 OpenAI-compatible 路由及 `/models` 自动发现。 -旧版 `mutsumi.providers` / `mutsumi.models` 配置仅用于迁移。升级时可接受安全迁移提示,或手动运行 **Mutsumi: 迁移旧版提供商凭据**。若密钥曾提交到版本控制,请在服务商侧轮换。 +Mutsumi 仅接受当前带版本标识的 `.mtm` 格式和当前提供商设置。旧文件请通过独立迁移项目转换,然后在 **Mutsumi: 管理模型提供商** 中重新录入凭据。 + +VS Code 内置的 **+ Markdown** 按钮会添加仅供用户查看的注释。Markdown 源文本及其位置会保存到 `.mtm` 文件,但不会发送给模型,也不会进入会话压缩或标题生成。 > **注意:** 本 Agent 框架针对 Kimi 基模家族调性优化设计,强烈建议使用 `kimi-for-coding`。 diff --git a/docs/custom-renderer-target-state.md b/docs/custom-renderer-target-state.md index d2372d0..8d6547c 100644 --- a/docs/custom-renderer-target-state.md +++ b/docs/custom-renderer-target-state.md @@ -47,7 +47,7 @@ export interface RenderData { - L1 跨轮锁定: `commitRoundUI()` → 所有 active 内容移入 committed - L2 轮内子段锁定: - reasoning → locked 当 content 开始到达 - - content → locked 当 tool_calls 开始到达 + - content → locked 当原生 `toolCall` 内容块开始到达 - L3 工具级锁定: 每个工具执行完毕后 appendBlock 到 committed,前一个工具自然锁定 **公开接口:** @@ -173,8 +173,8 @@ const rendererCtx = await esbuild.context({ ## LiteAdapter 分析结论 LiteAdapter **不需要额外处理**。原因: -- `generateTitle()` 和 `compressConversation` 从 `runner.run()` 返回的 `newMessages` 提取结果 -- `newMessages` 中的 `content` 直接来自 LLM 流式累积 (`roundContent`),与 `replaceOutput`/`outputBuffer` 完全无关 +- `generateTitle()` 和 `compressConversation` 只在 `runner.run()` 返回 `completed` 时从原生 `messages` 提取结果 +- `messages` 中的 assistant 是 pi-ai 终态消息,与 `replaceOutput`/`outputBuffer` 完全无关 - `getCurrentOutput()` 仅被 `httpServer/chat.ts` 调用 (HeadlessAdapter),LiteAdapter 的 `outputBuffer` 无人外部读取 ## SSE 改进 (Phase 2 方向,Phase 1 仅签名适配) @@ -184,7 +184,9 @@ LiteAdapter **不需要额外处理**。原因: ``` { event: 'block', data: RenderBlock JSON } { event: 'active', data: RenderData.active JSON } -{ event: 'done', data: { messageCount: N } } +{ type: 'done', messageCount: N } +{ type: 'error', code: '...', error: '...', messageCount: N } +{ type: 'cancelled', messageCount: N } ``` Phase 1 仅适配 `replaceOutput` 签名,SSE delta 逻辑暂不动。 diff --git a/docs/mtm-format.md b/docs/mtm-format.md new file mode 100644 index 0000000..dc74923 --- /dev/null +++ b/docs/mtm-format.md @@ -0,0 +1,28 @@ +# `.mtm` format version 1 + +Mutsumi accepts one on-disk format. Every file has this top-level shape: + +```json +{ + "formatVersion": 1, + "metadata": {}, + "context": [], + "notes": [{ "beforeUserIndex": 0, "markdown": "# Private note" }] +} +``` + +`context` contains messages with a strict semantic core: + +- `user` requires a role and valid text/multimodal `content`; +- `assistant` requires a role, valid native content blocks, and `api`/`provider`/`model` identity; +- `toolResult` requires its tool-call ID/name, valid content blocks, and `isError`. + +Provider envelope fields such as `usage`, cost, timestamps, stop reason, response metadata, errors, diagnostics, and signatures are preserved as opaque JSON. Missing or differently shaped envelope fields do not make the file invalid. Immediately before a provider request, Mutsumi creates a temporary pi-ai-compatible copy: invalid/missing usage becomes an all-zero value, timestamp becomes `0`, and stop reason is inferred as `toolUse` or `stop`. These defaults are never written back to disk. + +`notes` is optional. Each entry stores the Markdown source of a user annotation. `beforeUserIndex` is the number of user cells before that note; array order preserves multiple notes in the same gap. Markup notes are restored in the Notebook but never enter Agent history, title generation, compression, ghost-block indexing, or a provider prompt. + +System instructions are assembled dynamically and passed through `Context.systemPrompt`; they are never stored as messages. A user message may contain a `mutsumi.ghostBlock` extension. Assistant and tool-result messages may not contain Mutsumi extensions. + +Consecutive user messages are valid pending turns and remain separate on disk and as Code cells. At the provider boundary only, adjacent users are merged with a blank-line separator; multimodal block order is preserved, and the last user's timestamp wins. Merging never crosses an assistant or tool result. A user message is still invalid while a preceding tool call is waiting for its result. + +Files without `formatVersion: 1`, old OpenAI-shaped messages, malformed core message fields, and invalid tool-result ordering are rejected without being rewritten. Conversion belongs to the standalone migration project. If an open Notebook buffer contains malformed `mutsumi_interaction` metadata, Mutsumi ignores that entire interaction group and retains its Code cell as a pending user turn. diff --git a/docs/multi-provider-refactor.md b/docs/multi-provider-refactor.md index e92ddf3..03a36af 100644 --- a/docs/multi-provider-refactor.md +++ b/docs/multi-provider-refactor.md @@ -1,165 +1,14 @@ -# Multi-Provider Configuration +# Current model-provider architecture -> Superseded by the pi-ai provider registry and SecretStorage integration. `mutsumi.providers` and `mutsumi.models` below describe the one-release migration input only; do not add new API keys to settings. Use **Mutsumi: Manage Model Providers** and `mutsumi.customProviders` instead. +Mutsumi uses the `@earendil-works/pi-ai` provider catalog as its only model runtime. Built-in providers and models come from that catalog; user-defined OpenAI-compatible routes are configured through `mutsumi.customProviders`. -This document is retained as a record of the legacy settings-based multi-provider design. The current runtime uses pi-ai catalogs, SecretStorage credentials, and automatic model discovery. +Credentials are entered with **Mutsumi: Manage Model Providers** and stored in VS Code SecretStorage. Provider selections are always explicit `{ provider, model }` pairs. Provider IDs are exact and are never inferred, aliased, or selected by first match. -## Overview +The active settings are: -A model selection is always an explicit `{ model, provider }` pair. The system never infers a provider from ordering when more than one provider declares the same model. There is no compatibility layer for legacy string-valued settings or persisted agents missing an explicit provider. +- `mutsumi.customProviders`: non-secret custom route definitions. +- `mutsumi.defaultModel`: the default `{ provider, model }` pair. +- `mutsumi.titleGeneratorModel`: optional title-generation pair. +- `mutsumi.compressModel`: optional conversation-compression pair. -## Configuration - -### `mutsumi.providers` - -Array of provider objects using snake_case for settings schema alignment: - -```json -{ - "mutsumi.providers": [ - { - "name": "kimi-for-coding", - "baseurl": "https://api.kimi.com/coding/v1", - "api_key": "" - } - ] -} -``` - -- `name`: provider identifier -- `baseurl`: API base URL -- `api_key`: API key; may be empty in settings, but runtime credential use will report a configuration error until filled - -### `mutsumi.models` - -Provider-to-models mapping. Key is the provider name, value is the array of model identifiers supported by that provider: - -```json -{ - "mutsumi.models": { - "kimi-for-coding": ["kimi-for-coding"] - } -} -``` - -### `mutsumi.defaultModel`, `mutsumi.titleGeneratorModel`, `mutsumi.compressModel` - -All three are objects with required `model` and `provider`: - -```json -{ - "mutsumi.defaultModel": { - "model": "kimi-for-coding", - "provider": "kimi-for-coding" - } -} -``` - -Legacy string values are rejected by the schema and by runtime type guards. - -## Built-in Defaults - -When no providers are configured, Mutsumi falls back to: - -```typescript -const DEFAULT_PROVIDERS: Provider[] = [ - { name: "kimi-for-coding", baseurl: "https://api.kimi.com/coding/v1", api_key: "" } -]; - -const DEFAULT_MODELS: Record = { - "kimi-for-coding": ["kimi-for-coding"] -}; - -const DEFAULT_MODEL_SELECTION: ModelSelection = { - model: "kimi-for-coding", - provider: "kimi-for-coding" -}; -``` - -The built-in default `api_key` is intentionally empty so users can fill it via settings; a missing key produces a runtime configuration error only when credentials are actually requested. - -## Resolution Gate - -`resolveModelSelection(selection)` in `src/utils.ts` is the single validation gate: - -1. Verify `selection` is an object with non-empty string `model` and `provider` -2. Trim both names -3. Verify the provider exists -4. Verify the provider declares the model -5. Return the canonical `{ model, provider }` pair - -Any failure throws a descriptive error. There is no first-match fallback, no provider inference, and no legacy string handling. - -## Credential Lookup - -`getModelCredentials(model, provider)` requires both values, validates them through `resolveModelSelection`, then returns `{ apiKey, baseUrl }`. Empty `baseurl` or `api_key` throws a descriptive error. - -## Agent Default Resolution - -`resolveAgentDefaults(agentType, options?)` in `src/config/resolver.ts` applies the following chain: - -```text -options.modelSelection > AgentTypeConfig.defaultModel > mutsumi.defaultModel > error -``` - -All hardcoded model fallbacks have been removed. - -## Persistence - -Agent notebook metadata stores the pair flatly: - -```typescript -interface AgentMetadata { - model?: string; - provider?: string; -} -``` - -New agents always persist both. Legacy files missing `provider` produce a migration/configuration error at execution time. - -The single write point for mutating the persisted pair is `AgentFileOperations.updateAgentModelSelection(fileUri, selection)`, which uses `NotebookEdit.updateNotebookMetadata` when the notebook is open and raw file I/O otherwise. - -## Creation Paths - -1. **Root/entry agents** — `MutsumiSerializer.createDefaultContent()` resolves the complete pair through `resolveAgentDefaults()` and persists both fields. -2. **Dispatched children** — `AgentFileOperations.createAgentFile()` accepts an optional `ModelSelection`, resolves through the resolver chain, validates through the gate, and persists both fields. -3. **Compression output** — `compressConversation.ts` validates the source metadata pair through `resolveModelSelection()` before producing a new `.mtm`. Invalid source → error, no file created. The new file inherits the validated pair. - -## HTTP Contract - -### `PUT /agent/:uuid/model` - -Body must contain complete `{ model, provider }`. Missing either → `400`. Invalid pair → `400`. Persisted atomically via `AgentFileOperations.updateAgentModelSelection`, then the cached `HeadlessAdapter` session metadata is synchronized. - -### `POST /agent/:uuid/chat` - -Body `model`/`provider` are all-or-nothing: - -- Both present → validate, use for this request, and persist as the agent's new selection -- Neither present → use persisted pair; missing `model` → fall back to global default selection; `model` without `provider` → `400` migration error -- Exactly one present → `400` - -## Execution Paths - -- `src/controller.ts` removes the old `gpt-3.5-turbo` fallback. Notebook metadata rules match the HTTP chat contract. -- `src/agent/agentRunner.ts` title generation reads `mutsumi.titleGeneratorModel`, then falls back to the session metadata pair, then skips. -- `src/agent/titleGenerator.ts` uses `TitleGeneratorConfig { modelSelection?: ModelSelection }` and resolves credentials with `getModelCredentials(model, provider)`. -- `src/notebook/commands/compressConversation.ts` uses `getCompressModelSelection()` and validates the source pair before producing output. - -## Display - -QuickPick and tool output format the selection as `model (provider)`, for example `kimi-for-coding (kimi-for-coding)`. - -## Error Handling - -All core validation errors are descriptive English strings. UI layers wrap them with `t()` where appropriate. HTTP endpoints return `400` for invalid pairs and `500` for unexpected failures. - -## Same Model Names Across Providers - -When the same model identifier appears under multiple providers, the explicit provider in the selection disambiguates it. There is no first-match substitution. - -## Out of Scope - -- No migration layer for legacy string settings or pre-provider metadata -- No provider field in `AgentRunOptions` or `AgentSessionConfig` -- No changes to adapter interfaces +Old settings and plaintext credentials are not read by this extension. They must be handled outside this repository, and credentials must be entered again through the provider manager. diff --git a/docs/reasoning-effort-target-state.md b/docs/reasoning-effort-target-state.md index e3b8513..8488748 100644 --- a/docs/reasoning-effort-target-state.md +++ b/docs/reasoning-effort-target-state.md @@ -158,11 +158,11 @@ body 新增可选 reasoning_effort:同一值域校验,瞬态覆盖本次请 **确认无需改动(已核实):** - `src/agent/llmStream.ts`(只消费 stream,不组请求) -- 渲染/序列化链路(`uiRenderer.ts` / `renderer.ts` / `serializer.ts`):`reasoning_content` 的流式渲染、提交、`.mtm` round-trip 已完整存在 +- 渲染/序列化链路(`uiRenderer.ts` / `renderer.ts` / `serializer.ts`):pi-ai `thinking` 内容块的流式渲染、提交、`.mtm` round-trip 已完整存在 - `src/agent/fileOps.ts`(`sanitizeAgentFile` 保留未知 metadata key;新建 agent 无覆盖即不发送,符合 D4) - `src/agent/titleGenerator.ts`、`src/notebook/commands/compressConversation.ts`(D5:不传即默认,**零改动**——这是设计要求而非遗漏) - `src/notebook/commands/index.ts`、`src/notebook/toolbar.ts`(D8:无新命令,注册链不变) -- Preserved Thinking 回传:`agentRunner` 已将 `reasoning_content` 写回 messages,天然满足 Kimi/DeepSeek 要求 +- Preserved Thinking 回传:`agentRunner` 直接保存 pi-ai 原生 assistant message 及其 thinking signatures,满足跨轮连续性要求 ## 7. 边界与异常 diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 9af5404..35413cf 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -160,13 +160,11 @@ "providers.modelCountUnconfigured": "{0} models • API key not configured", "providers.addCustom": "Add custom OpenAI-compatible provider", "providers.failed": "Provider management failed: {0}", - "migration.conflicts": "Different plaintext keys exist for the same global route: {0}. Rename those routes or keep one key before migrating.", - "migration.routeConflicts": "Legacy custom routes conflict with built-in provider IDs: {0}. Rename those routes before migrating.", - "migration.rotationWarning": "Provider keys were moved to VS Code SecretStorage. Rotate any key that was committed to workspace or version-control history.", - "migration.noneFound": "No legacy plaintext provider credentials were found.", - "migration.failed": "Provider credential migration failed: {0}", - "migration.action": "Migrate securely", - "migration.prompt": "Mutsumi found plaintext LLM API keys in settings. Move them to VS Code SecretStorage now?", + "serializer.unsupportedFormat": "Unsupported .mtm format (expected {0}, received {1}). Convert this file with the standalone migration tool before opening it.", + "serializer.invalidFormat": "Invalid .mtm file: {0}", + "serializer.standaloneMessagesUnsupported": "Standalone assistant/toolResult messages are not valid in .mtm format version {0}", + "serializer.standaloneAssistantSerializationUnsupported": "Standalone assistant cells cannot be serialized in .mtm format version {0}", + "serializer.standaloneAssistantCellUnsupported": "Standalone assistant cells are not valid in .mtm format version {0}", "renameSession.prompt": "Enter new session title (leave empty to auto-generate)", "renameSession.renamed": "Session renamed: {0}", diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index 1a1ac4c..d05fdbf 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -160,13 +160,11 @@ "providers.modelCountUnconfigured": "{0} 个模型 • 尚未配置 API Key", "providers.addCustom": "添加自定义 OpenAI-compatible 提供商", "providers.failed": "提供商管理失败:{0}", - "migration.conflicts": "同一全局路由存在不同的明文密钥:{0}。请先重命名路由或仅保留一个密钥,再执行迁移。", - "migration.routeConflicts": "旧版自定义路由与内置提供商 ID 冲突:{0}。请先重命名这些路由,再执行迁移。", - "migration.rotationWarning": "提供商密钥已迁移到 VS Code SecretStorage。若密钥曾提交到工作区或版本历史,请在服务商侧轮换。", - "migration.noneFound": "未发现旧版明文提供商凭据。", - "migration.failed": "提供商凭据迁移失败:{0}", - "migration.action": "安全迁移", - "migration.prompt": "Mutsumi 在设置中发现了明文 LLM API Key。现在将其迁移到 VS Code SecretStorage 吗?", + "serializer.unsupportedFormat": "不支持的 .mtm 格式(应为 {0},实际为 {1})。请先使用独立迁移工具转换此文件。", + "serializer.invalidFormat": ".mtm 文件无效:{0}", + "serializer.standaloneMessagesUnsupported": "独立的 assistant/toolResult 消息不适用于 .mtm 格式版本 {0}", + "serializer.standaloneAssistantSerializationUnsupported": "独立的 assistant 单元格无法序列化为 .mtm 格式版本 {0}", + "serializer.standaloneAssistantCellUnsupported": "独立的 assistant 单元格不适用于 .mtm 格式版本 {0}", "renameSession.prompt": "输入新的会话标题(留空则自动生成)", "renameSession.renamed": "会话已重命名: {0}", diff --git a/package.json b/package.json index 78b7810..04e814a 100644 --- a/package.json +++ b/package.json @@ -124,12 +124,6 @@ "category": "Mutsumi", "icon": "$(key)" }, - { - "command": "mutsumi.migrateProviderCredentials", - "title": "%command.migrateProviderCredentials.title%", - "category": "Mutsumi", - "icon": "$(shield)" - }, { "command": "mutsumi.renameSession", "title": "%command.renameSession.title%", @@ -410,46 +404,6 @@ "configuration": { "title": "%configuration.title%", "properties": { - "mutsumi.providers": { - "type": "array", - "deprecationMessage": "Deprecated: use Mutsumi: Manage Model Providers. API keys are now stored in VS Code SecretStorage.", - "markdownDescription": "%configuration.providers.markdownDescription%", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "markdownDescription": "%configuration.providers.items.name.markdownDescription%" - }, - "baseurl": { - "type": "string", - "markdownDescription": "%configuration.providers.items.baseurl.markdownDescription%" - }, - "api_key": { - "type": "string", - "default": "", - "markdownDescription": "%configuration.providers.items.api_key.markdownDescription%" - } - }, - "required": [ - "name", - "baseurl", - "api_key" - ] - }, - "default": [] - }, - "mutsumi.models": { - "type": "object", - "deprecationMessage": "Deprecated: built-in catalogs and custom provider model discovery replace this setting.", - "markdownDescription": "%configuration.models.markdownDescription%", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, "mutsumi.customProviders": { "type": "object", "markdownDescription": "%configuration.customProviders.markdownDescription%", diff --git a/package.nls.json b/package.nls.json index b580ca0..435de92 100644 --- a/package.nls.json +++ b/package.nls.json @@ -17,7 +17,6 @@ "command.customRequestAction.title": "Inspect", "command.selectModel.title": "Select Model", "command.manageProviders.title": "Manage Model Providers", - "command.migrateProviderCredentials.title": "Migrate Provider Credentials", "command.renameSession.title": "Rename Session", "command.debugContext.title": "Debug Context", "command.pruneGhostBlocks.title": "Prune Outdated References", @@ -41,11 +40,6 @@ "command.removeShellTask.title": "Remove", "configuration.title": "Mutsumi", - "configuration.providers.markdownDescription": "**Deprecated migration-only setting.** Use **Mutsumi: Manage Model Providers**. Existing plaintext keys can be moved to VS Code SecretStorage with **Mutsumi: Migrate Legacy Provider Credentials**.", - "configuration.providers.items.name.markdownDescription": "LLM API Provider Name (e.g., OpenAI, Anthropic, llama.cpp)", - "configuration.providers.items.baseurl.markdownDescription": "LLM API BaseURL (e.g., https://api.openai.com/v1, http://localhost:8080/v1)", - "configuration.providers.items.api_key.markdownDescription": "Deprecated plaintext API key. Do not add new secrets here; use the provider manager.", - "configuration.models.markdownDescription": "**Deprecated migration-only setting.** Built-in catalogs and automatic model discovery replace this mapping.", "configuration.customProviders.markdownDescription": "Non-secret custom OpenAI-compatible provider routes. Configure API keys with **Mutsumi: Manage Model Providers**; never place keys here.", "configuration.defaultModel.markdownDescription": "Default `{ provider, model }` selection. Configure credentials and browse supported models with **Mutsumi: Manage Model Providers**.", "configuration.titleGeneratorModel.markdownDescription": "Model selection used for generating agent titles. Must be an object with `model` and `provider`. If empty, falls back to the session metadata pair.", @@ -57,7 +51,7 @@ "configuration.httpServer.password.description": "Bearer token password for the Mutsumi HTTP Server. Stored in PLAINTEXT in settings. If empty while the server is enabled, the server refuses to start. Use the 'Mutsumi: Generate HTTP Server Password' command to create one.", "configuration.httpServer.host.description": "Address the HTTP Server binds to. WARNING: changing this to 0.0.0.0 exposes the server to your LAN or the public internet — set a strong password (mutsumi.httpServer.password) first.", "configuration.httpServer.port.description": "Starting port for the HTTP Server. If occupied, subsequent ports are scanned (up to +100).", - "configuration.agentConfig.markdownDescription": "Agent type & tool set configuration. Overrides built-in defaults. Leave empty `{}` to use built-in defaults.\n\nShape:\n```json\n\"mutsumi.agentConfig\": {\n \"toolSets\": {\n \"read\": [\"read\", \"glob\"],\n \"deliver\": [\"shell\", \"write\"]\n },\n \"agentTypes\": {\n \"chat\": {\n \"toolSets\": [],\n \"defaultModel\": \"kimi-for-coding\",\n \"defaultRules\": [\"default/chat.md\"],\n \"defaultSkills\": [],\n \"allowedChildTypes\": [],\n \"isEntry\": true\n }\n }\n}\n```\n\n`toolSets`: each key maps to an array of tool names. Given names fully replace the built-in tool set. New names add new tool sets.\n\n`agentTypes`: for a type that exists in built-in defaults, fields you provide override the built-in fields (fields you omit are kept from defaults). For a new type, provide all required fields.\n\nNote: `version` is not configurable here; it is fixed to 1 internally.", + "configuration.agentConfig.markdownDescription": "Agent type & tool set configuration. Overrides built-in defaults. Leave empty `{}` to use built-in defaults.\n\nShape:\n```json\n\"mutsumi.agentConfig\": {\n \"toolSets\": {\n \"read\": [\"read\", \"glob\"],\n \"deliver\": [\"shell\", \"write\"]\n },\n \"agentTypes\": {\n \"chat\": {\n \"toolSets\": [],\n \"defaultModel\": { \"provider\": \"kimi-coding\", \"model\": \"kimi-for-coding\" },\n \"defaultRules\": [\"default/chat.md\"],\n \"defaultSkills\": [],\n \"allowedChildTypes\": [],\n \"isEntry\": true\n }\n }\n}\n```\n\n`toolSets`: each key maps to an array of tool names. Given names fully replace the built-in tool set. New names add new tool sets.\n\n`agentTypes`: for a type that exists in built-in defaults, fields you provide override the built-in fields (fields you omit are kept from defaults). For a new type, provide all required fields.\n\nNote: `version` is not configurable here; it is fixed to 1 internally.", "configuration.mcpServers.markdownDescription": "MCP servers managed by Mutsumi. This is the only MCP configuration source; VS Code mcp.json is not read. Configure an object keyed by stable server ID. Stdio servers require `type`, `command`, and optional `args`, `cwd`, `env`, and positive `timeout`; HTTP servers require `type`, an absolute HTTP(S) `url`, and optional `headers` and positive `timeout`.", "configuration.agentConfig.defaultMcpServers.markdownDescription": "MCP server IDs whose currently discovered tools are frozen into new Agent sessions. This affects creation only, not existing sessions or server connection lifetime." } diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index f94b241..b46bdbe 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -17,7 +17,6 @@ "command.customRequestAction.title": "检查", "command.selectModel.title": "选择模型", "command.manageProviders.title": "管理模型提供商", - "command.migrateProviderCredentials.title": "迁移提供商凭据", "command.renameSession.title": "重命名会话", "command.debugContext.title": "调试上下文", "command.pruneGhostBlocks.title": "裁剪过期引用", @@ -41,11 +40,6 @@ "command.removeShellTask.title": "移除", "configuration.title": "Mutsumi", - "configuration.providers.markdownDescription": "**仅用于旧版迁移,已废弃。** 请使用“**Mutsumi: 管理模型提供商**”。现有明文密钥可通过“**Mutsumi: 迁移旧版提供商凭据**”移入 VS Code SecretStorage。", - "configuration.providers.items.name.markdownDescription": "LLM API 提供商名称(例如 OpenAI、Anthropic、llama.cpp)", - "configuration.providers.items.baseurl.markdownDescription": "LLM API BaseURL(例如 https://api.openai.com/v1、http://localhost:8080/v1)", - "configuration.providers.items.api_key.markdownDescription": "已废弃的明文 API Key。请勿在此添加新密钥,改用提供商管理命令。", - "configuration.models.markdownDescription": "**仅用于旧版迁移,已废弃。** 内置目录和自动模型发现已取代此映射。", "configuration.customProviders.markdownDescription": "不含秘密的自定义 OpenAI-compatible 提供商路由。请通过“管理模型提供商”命令配置 API Key,切勿在此填写密钥。", "configuration.defaultModel.markdownDescription": "默认 `{ provider, model }` 选择。请通过“**Mutsumi: 管理模型提供商**”配置凭据和浏览支持的模型。", "configuration.titleGeneratorModel.markdownDescription": "用于生成 Agent 标题的模型选择。必须是包含 `model` 与 `provider` 的对象。若为空,则回退到会话 metadata 中的模型对。", @@ -57,7 +51,7 @@ "configuration.httpServer.password.description": "Mutsumi HTTP Server 的 Bearer 令牌密码。以明文形式存储在设置中。若启用服务器但密码为空,服务器将拒绝启动。可使用“Mutsumi: 生成 HTTP Server 密码”命令创建密码。", "configuration.httpServer.host.description": "HTTP Server 绑定的地址。警告:将其改为 0.0.0.0 会将服务器暴露给局域网或公网——请先设置强密码(mutsumi.httpServer.password)。", "configuration.httpServer.port.description": "HTTP Server 的起始端口。若被占用,将扫描后续端口(最多 +100)。", - "configuration.agentConfig.markdownDescription": "Agent 类型与工具集配置。覆盖内置默认值。留空 `{}` 则使用内置默认值。\n\n结构:\n```json\n\"mutsumi.agentConfig\": {\n \"toolSets\": {\n \"read\": [\"read\", \"glob\"],\n \"deliver\": [\"shell\", \"write\"]\n },\n \"agentTypes\": {\n \"chat\": {\n \"toolSets\": [],\n \"defaultModel\": \"kimi-for-coding\",\n \"defaultRules\": [\"default/chat.md\"],\n \"defaultSkills\": [],\n \"allowedChildTypes\": [],\n \"isEntry\": true\n }\n }\n}\n```\n\n`toolSets`:每个键映射到工具名数组。给定的名称将完全替换内置工具集。新名称将添加新的工具集。\n\n`agentTypes`:对于内置默认值中已存在的类型,提供的字段会覆盖内置字段(省略的字段保留默认值)。对于新类型,请提供所有必填字段。\n\n注意:`version` 在此处不可配置,内部固定为 1。", + "configuration.agentConfig.markdownDescription": "Agent 类型与工具集配置。覆盖内置默认值。留空 `{}` 则使用内置默认值。\n\n结构:\n```json\n\"mutsumi.agentConfig\": {\n \"toolSets\": {\n \"read\": [\"read\", \"glob\"],\n \"deliver\": [\"shell\", \"write\"]\n },\n \"agentTypes\": {\n \"chat\": {\n \"toolSets\": [],\n \"defaultModel\": { \"provider\": \"kimi-coding\", \"model\": \"kimi-for-coding\" },\n \"defaultRules\": [\"default/chat.md\"],\n \"defaultSkills\": [],\n \"allowedChildTypes\": [],\n \"isEntry\": true\n }\n }\n}\n```\n\n`toolSets`:每个键映射到工具名数组。给定的名称将完全替换内置工具集。新名称将添加新的工具集。\n\n`agentTypes`:对于内置默认值中已存在的类型,提供的字段会覆盖内置字段(省略的字段保留默认值)。对于新类型,请提供所有必填字段。\n\n注意:`version` 在此处不可配置,内部固定为 1。", "configuration.mcpServers.markdownDescription": "由 Mutsumi 管理的 MCP 服务器。这是唯一的 MCP 配置来源,不读取 VS Code 的 mcp.json。使用稳定服务器 ID 为键的对象配置。stdio 服务器需要 `type`、`command`,可选 `args`、`cwd`、`env` 与正数 `timeout`;HTTP 服务器需要 `type`、绝对 HTTP(S) `url`,可选 `headers` 与正数 `timeout`。", "configuration.agentConfig.defaultMcpServers.markdownDescription": "其当前已发现工具会被冻结到新建 Agent 会话中的 MCP 服务器 ID。仅影响创建,不影响已有会话或服务器连接生命周期。" } diff --git a/src/adapters/headlessAdapter.ts b/src/adapters/headlessAdapter.ts index be37cc7..22d9d9e 100644 --- a/src/adapters/headlessAdapter.ts +++ b/src/adapters/headlessAdapter.ts @@ -3,8 +3,8 @@ import { v4 as uuidv4 } from 'uuid'; import { MutsumiSerializer } from '../notebook/serializer'; import { messagesToGenericCells, - genericCellsToMessages, - extractGhostBlocksFromCells + extractGhostBlocksFromCells, + extractNotebookNotes, } from '../notebook/serializer'; import { IAgentAdapter, @@ -12,9 +12,10 @@ import { AgentSessionConfig, CreateSessionOptions } from './interfaces'; -import type { AgentMessage, AgentMetadata, AgentContext, ContextItem } from '../types'; +import type { AgentMetadata, ContextItem, PersistedAgentMessage } from '../types'; import { GhostBlock } from '../contextManagement/interfaces'; import { isEmptyGhostBlock } from '../contextManagement/ghostBlocks'; +import { decodeAgentContext, encodeAgentContext } from '../mtmFormat'; /** * Reads a reasoning effort override directly from an agent file. @@ -23,7 +24,7 @@ import { isEmptyGhostBlock } from '../contextManagement/ghostBlocks'; */ export async function readReasoningEffortFromFile(fileUri: vscode.Uri): Promise { const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)) as AgentContext; + const data = decodeAgentContext(content); return data.metadata?.reasoning_effort; } @@ -37,7 +38,7 @@ export async function writeReasoningEffortToFile( effort: string | undefined ): Promise { const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)) as AgentContext; + const data = decodeAgentContext(content); if (effort === undefined || effort === 'default') { delete data.metadata.reasoning_effort; @@ -45,7 +46,7 @@ export async function writeReasoningEffortToFile( data.metadata.reasoning_effort = effort; } - const encoded = new TextEncoder().encode(JSON.stringify(data, null, 2)); + const encoded = encodeAgentContext(data); await vscode.workspace.fs.writeFile(fileUri, encoded); } @@ -101,8 +102,9 @@ export class HeadlessAgentSession implements IAgentSession { private readonly tokenSource = new vscode.CancellationTokenSource(); private readonly resourceUri?: vscode.Uri; private config: AgentSessionConfig; - private history: AgentMessage[] = []; // Raw (unexpanded) history from file - private fullHistory: AgentMessage[] | undefined; // Full expanded history from setHistory + private history: PersistedAgentMessage[] = []; + private historyLoaded = false; + private fullHistory: PersistedAgentMessage[] | undefined; private inputPrompt = ''; private outputBuffer = ''; private pendingGhostBlock?: GhostBlock | null; // Ghost block for current message (applied on save) @@ -125,14 +127,12 @@ export class HeadlessAgentSession implements IAgentSession { this.inputPrompt = prompt; } - async getHistory(): Promise { - if (this.resourceUri && this.history.length === 0) { - try { + async getHistory(): Promise { + if (this.resourceUri && !this.historyLoaded) { const content = await vscode.workspace.fs.readFile(this.resourceUri); - const data = JSON.parse(new TextDecoder().decode(content)) as AgentContext; - if (Array.isArray(data.context)) { - this.history = data.context; - } + const data = decodeAgentContext(content); + this.history = data.context; + this.historyLoaded = true; if (data.metadata) { if (data.metadata.model && !this.config.model) { this.config.model = data.metadata.model; @@ -153,16 +153,14 @@ export class HeadlessAgentSession implements IAgentSession { this.config.metadata.provider = data.metadata.provider; } } - } catch { - // Ignore, return cached history - } } - return this.history; + return [...this.history]; } - setHistory(history: AgentMessage[]): void { - // Store the full expanded history + setHistory(history: PersistedAgentMessage[]): void { this.fullHistory = history; + this.history = history; + this.historyLoaded = true; } async appendOutput(content: string, _options?: { isMarkdown?: boolean; mimeType?: string }): Promise { @@ -182,14 +180,14 @@ export class HeadlessAgentSession implements IAgentSession { const serializer = new MutsumiSerializer(); const tokenSource = new vscode.CancellationTokenSource(); - let notebookData: vscode.NotebookData | undefined; - - try { - const raw = await vscode.workspace.fs.readFile(this.resourceUri); - notebookData = await serializer.deserializeNotebook(raw, tokenSource.token); - } catch { - notebookData = new vscode.NotebookData([]); - } + const raw = await vscode.workspace.fs.readFile(this.resourceUri); + const notebookData = await serializer.deserializeNotebook(raw, tokenSource.token); + const existingGenericCells = notebookData.cells.map(cell => ({ + kind: cell.kind === vscode.NotebookCellKind.Code ? 2 as const : 1 as const, + value: cell.value, + metadata: cell.metadata, + })); + const notes = extractNotebookNotes(existingGenericCells); if (!notebookData.metadata) { notebookData.metadata = { @@ -203,7 +201,7 @@ export class HeadlessAgentSession implements IAgentSession { // Use generic cell conversion for consistent behavior const sourceHistory = this.fullHistory || this.history; - const genericCells = messagesToGenericCells(sourceHistory); + const genericCells = messagesToGenericCells(sourceHistory, notes); // Apply the current ghost block to the last user cell if exists if (this.pendingGhostBlock !== undefined && genericCells.length > 0) { diff --git a/src/adapters/interfaces.ts b/src/adapters/interfaces.ts index 1bc8cd3..1030823 100644 --- a/src/adapters/interfaces.ts +++ b/src/adapters/interfaces.ts @@ -4,7 +4,7 @@ */ import * as vscode from 'vscode'; -import { AgentMessage, AgentMetadata, ContextItem } from '../types'; +import { AgentMetadata, ContextItem, PersistedAgentMessage } from '../types'; import { GhostBlock } from '../contextManagement/interfaces'; /** @@ -88,7 +88,7 @@ export interface IAgentSession { /** * Get the full conversation history. */ - getHistory(): Promise; + getHistory(): Promise; /** * Append output content (streaming UI updates). @@ -129,7 +129,7 @@ export interface IAgentSession { * Set the full interaction history to be saved. * Used by NotebookAdapter to persist cell-specific history. */ - setHistory(messages: AgentMessage[]): void; + setHistory(messages: PersistedAgentMessage[]): void; /** * Get the current output content. @@ -175,8 +175,8 @@ export interface CellMetadata { last_ghost_block?: GhostBlock; /** Message role (user/assistant) */ role?: string; - /** Pre-built interaction array for assistant cells */ - mutsumi_interaction?: AgentMessage[]; + /** Assistant/tool interaction rendered as output of a user cell */ + mutsumi_interaction?: PersistedAgentMessage[]; /** Other arbitrary metadata */ [key: string]: any; } diff --git a/src/adapters/liteAdapter.ts b/src/adapters/liteAdapter.ts index c1f7ec6..61b3491 100644 --- a/src/adapters/liteAdapter.ts +++ b/src/adapters/liteAdapter.ts @@ -6,7 +6,7 @@ import { AgentSessionConfig, CreateSessionOptions } from './interfaces'; -import { AgentMessage, ContextItem } from '../types'; +import { ContextItem, PersistedAgentMessage } from '../types'; import { GhostBlock } from '../contextManagement/interfaces'; import { isEmptyGhostBlock } from '../contextManagement/ghostBlocks'; @@ -16,7 +16,7 @@ import { isEmptyGhostBlock } from '../contextManagement/ghostBlocks'; */ export interface LiteAgentSessionConfig extends AgentSessionConfig { input?: string; - history?: AgentMessage[]; + history?: PersistedAgentMessage[]; } export class LiteAdapter implements IAgentAdapter { @@ -42,7 +42,7 @@ export class LiteAgentSession implements IAgentSession { private readonly tokenSource = new vscode.CancellationTokenSource(); private config: LiteAgentSessionConfig; private inputPrompt = ''; - private history: AgentMessage[] = []; + private history: PersistedAgentMessage[] = []; private outputBuffer = ''; private ghostBlocks: (GhostBlock | null)[] = []; @@ -58,8 +58,8 @@ export class LiteAgentSession implements IAgentSession { return this.inputPrompt; } - async getHistory(): Promise { - return this.history; + async getHistory(): Promise { + return [...this.history]; } async appendOutput(content: string, _options?: { isMarkdown?: boolean; mimeType?: string }): Promise { @@ -98,7 +98,7 @@ export class LiteAgentSession implements IAgentSession { } } - setHistory(messages: AgentMessage[]): void { + setHistory(messages: PersistedAgentMessage[]): void { this.history = messages; } diff --git a/src/adapters/notebookAdapter.ts b/src/adapters/notebookAdapter.ts index 66e0243..7e7c5ae 100644 --- a/src/adapters/notebookAdapter.ts +++ b/src/adapters/notebookAdapter.ts @@ -1,10 +1,11 @@ import * as vscode from 'vscode'; import { IAgentAdapter, IAgentSession, CreateSessionOptions, AgentSessionConfig } from './interfaces'; -import { AgentMessage, AgentMetadata, ContextItem } from '../types'; +import { AgentMetadata, ContextItem, PersistedAgentMessage } from '../types'; import { GhostBlock } from '../contextManagement/interfaces'; import { decodeGhostBlock, isEmptyGhostBlock } from '../contextManagement/ghostBlocks'; import { debugLogger } from '../debugLogger'; import { readReasoningEffortFromFile, writeReasoningEffortToFile } from './headlessAdapter'; +import { parsePersistedInteraction } from '../mtmFormat'; export class NotebookAdapter implements IAgentAdapter { constructor( @@ -86,8 +87,7 @@ export class NotebookAgentSession implements IAgentSession { public readonly id: string; public readonly token: vscode.CancellationToken; public readonly supportsUI = true; - private rawHistoryLength: number = 0; // Length of raw (unexpanded) history from getHistory - private fullHistory: AgentMessage[] | undefined; // Full expanded history set by setHistory + private fullHistory: PersistedAgentMessage[] | undefined; private config?: AgentSessionConfig; private pendingGhostBlock?: GhostBlock | null; private pendingContextItems?: ContextItem[]; @@ -116,43 +116,37 @@ export class NotebookAgentSession implements IAgentSession { return this.execution.cell.document.getText(); } - async getHistory(): Promise { + async getHistory(): Promise { debugLogger.log('[NotebookAdapter.getHistory] ==== START ===='); - // Build raw history from notebook cells - // Returns original stored messages WITHOUT expanding interactions - // This preserves metadata and maintains 1:1 correspondence with ghostBlocks - const history: AgentMessage[] = []; + // Build persisted history from Code cells and their validated output interactions. + const history: PersistedAgentMessage[] = []; const currentIndex = this.execution.cell.index; debugLogger.log(`[NotebookAdapter.getHistory] Current cell index: ${currentIndex}, iterating ${currentIndex} previous cells`); for (let i = 0; i < currentIndex; i++) { const cell = this.notebook.cellAt(i); - const role = cell.metadata?.role || 'user'; const content = cell.document.getText(); - debugLogger.log(`[NotebookAdapter.getHistory] Cell ${i}: kind=${cell.kind}, role=${role}, content length=${content.length}, metadata keys=${Object.keys(cell.metadata ?? {}).join(',')}`); - - if (content.trim()) { - if (role === 'user') { - // User message - store with cell metadata if any - history.push({ - role: 'user', - content, - metadata: cell.metadata - }); - debugLogger.log(`[NotebookAdapter.getHistory] - Added user message, has interaction=${!!cell.metadata?.mutsumi_interaction}`); - } else if (role === 'assistant') { - // Assistant message - preserve the full interaction in metadata - // Do NOT expand here - buildInteractionHistory will handle expansion - history.push({ - role: 'assistant', - content, - metadata: cell.metadata - }); - debugLogger.log(`[NotebookAdapter.getHistory] - Added assistant message, has interaction=${!!cell.metadata?.mutsumi_interaction}`); - } - } else { - debugLogger.log(`[NotebookAdapter.getHistory] - Skipped empty content cell`); + debugLogger.log(`[NotebookAdapter.getHistory] Cell ${i}: kind=${cell.kind}, content length=${content.length}, metadata keys=${Object.keys(cell.metadata ?? {}).join(',')}`); + + if (cell.kind !== vscode.NotebookCellKind.Code) { + debugLogger.log(`[NotebookAdapter.getHistory] - Skipped Markup note`); + continue; + } + + const userMessage: PersistedAgentMessage = { + role: 'user', + content, + timestamp: cell.metadata?.timestamp, + }; + const ghostBlock = decodeGhostBlock(cell.metadata?.last_ghost_block); + if (ghostBlock) userMessage.mutsumi = { ghostBlock }; + history.push(userMessage); + const interaction = parsePersistedInteraction(cell.metadata?.mutsumi_interaction); + if (interaction) history.push(...interaction); + else if (cell.metadata?.mutsumi_interaction !== undefined) { + debugLogger.log(`[NotebookAdapter.getHistory] - Ignored malformed interaction on cell ${i}`); } + debugLogger.log(`[NotebookAdapter.getHistory] - Added user message, interaction count=${interaction?.length ?? 0}`); } // Populate config from metadata if missing @@ -170,10 +164,7 @@ export class NotebookAgentSession implements IAgentSession { this.config.metadata = JSON.parse(JSON.stringify(metadata)) as AgentMetadata; } - // Record raw history length to calculate diff for save() - // This is the count of raw (unexpanded) messages BEFORE AgentRunner adds new messages - this.rawHistoryLength = history.length; - debugLogger.log(`[NotebookAdapter.getHistory] ==== END, returning ${history.length} messages, rawHistoryLength=${this.rawHistoryLength} ====`); + debugLogger.log(`[NotebookAdapter.getHistory] ==== END, returning ${history.length} messages ====`); return history; } @@ -208,8 +199,7 @@ export class NotebookAgentSession implements IAgentSession { ]); } - setHistory(messages: AgentMessage[]): void { - // Store the full expanded history (after buildInteractionHistory and AgentRunner processing) + setHistory(messages: PersistedAgentMessage[]): void { this.fullHistory = messages; } @@ -239,6 +229,10 @@ export class NotebookAgentSession implements IAgentSession { // 2. Cell Metadata Update const newCellMetadata: any = { ...this.execution.cell.metadata }; + if (!newCellMetadata.timestamp && this.fullHistory) { + const lastUser = [...this.fullHistory].reverse().find(message => message.role === 'user'); + if (lastUser) newCellMetadata.timestamp = lastUser.timestamp; + } // Apply pending ghost block if any if (this.pendingGhostBlock !== undefined) { @@ -252,7 +246,7 @@ export class NotebookAgentSession implements IAgentSession { // Calculate the new interaction for this cell if (this.fullHistory && this.fullHistory.length > 0) { - const newMessages: AgentMessage[] = []; + const newMessages: PersistedAgentMessage[] = []; for (let i = this.fullHistory.length - 1; i >= 0; i--) { const msg = this.fullHistory[i]; if (msg.role === 'user') { @@ -263,6 +257,8 @@ export class NotebookAgentSession implements IAgentSession { if (newMessages.length > 0) { newCellMetadata.mutsumi_interaction = newMessages; + } else { + delete newCellMetadata.mutsumi_interaction; } } @@ -383,7 +379,9 @@ export class NotebookAgentSession implements IAgentSession { for (let i = 0; i < currentIndex; i++) { const cell = this.notebook.cellAt(i); - ghostBlocks.push(decodeGhostBlock(cell.metadata?.last_ghost_block)); + if (cell.kind === vscode.NotebookCellKind.Code) { + ghostBlocks.push(decodeGhostBlock(cell.metadata?.last_ghost_block)); + } } return ghostBlocks; diff --git a/src/agent/agentRunner.ts b/src/agent/agentRunner.ts index 318f887..382d01d 100644 --- a/src/agent/agentRunner.ts +++ b/src/agent/agentRunner.ts @@ -9,14 +9,15 @@ import { AgentMessage } from '../types'; import { UIRenderer } from './uiRenderer'; import { MUTSUMI_AGENT_CHAT_MIME, RenderBlock } from '../notebook/renderTypes'; import { LLMStreamHandler } from './llmStream'; -import { ToolExecutor } from './toolExecutor'; +import { ToolExecutor, type ToolExecutionResult } from './toolExecutor'; import { TitleGenerator } from './titleGenerator'; import { LLMClient } from './llmClient'; import { IAgentSession, AgentSessionConfig } from '../adapters/interfaces'; import { LiteAgentSession } from '../adapters/liteAdapter'; import { debugLogger } from '../debugLogger'; import { getTitleModelSelection } from '../utils'; -import { AgentRunOptions } from './types'; +import { AgentRunContext, AgentRunOptions, AgentRunResult } from './types'; +import type { ToolCall } from '@earendil-works/pi-ai'; import { t } from '../i18n'; export { AgentRunOptions } from './types'; @@ -28,7 +29,7 @@ export { AgentRunOptions } from './types'; * @class AgentRunner * @example * const runner = new AgentRunner(options, toolSet, session); - * const newMessages = await runner.run(abortController, initialMessages); + * const result = await runner.run(abortController, initialContext); */ export class AgentRunner { /** Maximum number of tool interaction loops */ @@ -79,16 +80,15 @@ export class AgentRunner { * @description Runs the conversation loop with the LLM, handling streaming, * tool calls, and termination conditions. * @param {AbortController} abortController - Controller for cancellation - * @param {AgentMessage[]} initialMessages - Initial message history - * @returns {Promise} New messages generated during this run - * @throws {TerminationError} If task_finish tool is called + * @param {AgentRunContext} initialContext - Provider-ready prompt and message history + * @returns {Promise} Explicit status plus native messages safe to persist * @example - * const newMessages = await runner.run(abortController, messages); + * const result = await runner.run(abortController, context); */ async run( abortController: AbortController, - initialMessages: AgentMessage[] - ): Promise { + initialContext: AgentRunContext + ): Promise { // Get config from session at the start of run const config = await this.session.getConfig(); const allowedUris = config.allowedUris || []; @@ -105,23 +105,24 @@ export class AgentRunner { ); } - const messages = [...initialMessages]; + const messages = [...initialContext.messages]; const newMessages: AgentMessage[] = []; let loopCount = 0; + let status: AgentRunResult['status'] = 'completed'; + let failure: AgentRunResult['error']; while (loopCount < this.maxLoops) { if (this.session.token.isCancellationRequested) { + status = 'cancelled'; break; } loopCount++; - let roundContent = ''; - let roundReasoning = ''; - let toolCalls: any[] = []; - let replayState: import('../llm/types').PiAiReplayState | undefined; + let assistantMessage: Extract; try { const result = await this.llmStreamHandler.streamResponse( + initialContext.systemPrompt, messages, this.toolSet.getDefinitions(), abortController.signal, @@ -140,10 +141,7 @@ export class AgentRunner { await this.session.replaceOutput(JSON.stringify(renderData), { mimeType: MUTSUMI_AGENT_CHAT_MIME }); } ); - roundContent = result.roundContent; - roundReasoning = result.roundReasoning; - toolCalls = result.toolCalls; - replayState = result.replayState; + assistantMessage = result.message; } catch (error: any) { // Handle network/API errors gracefully const isCancellation = @@ -152,12 +150,17 @@ export class AgentRunner { abortController.signal.aborted; if (isCancellation) { - // User-initiated cancellation, just end gracefully + status = 'cancelled'; break; } // Network/API error - show notification and preserve history const errorMessage = error.message || String(error); + status = 'failed'; + failure = { + code: typeof error.code === 'string' && error.code ? error.code : 'LLM_STREAM_ERROR', + message: errorMessage, + }; console.error('LLM Stream Error:', error); // Show error as VSCode notification (non-modal) @@ -173,66 +176,82 @@ export class AgentRunner { const errorMarkdown = `\n\n> ⚠️ **Error**: ${errorMessage.replace(/\n/g, ' ')}\n\n*Execution stopped due to network error. Previous output is preserved above.*`; this.uiRenderer.appendBlock({ type: 'content', markdown: errorMarkdown }); - await this.session.replaceOutput(JSON.stringify(this.uiRenderer.getCommittedRenderData()), { mimeType: MUTSUMI_AGENT_CHAT_MIME }); + try { + await this.session.replaceOutput(JSON.stringify(this.uiRenderer.getCommittedRenderData()), { mimeType: MUTSUMI_AGENT_CHAT_MIME }); + } catch (renderError) { + console.error('Failed to render LLM error state:', renderError); + } break; } + const textBlocks = assistantMessage.content.filter(block => block.type === 'text'); + const thinkingBlocks = assistantMessage.content.filter(block => block.type === 'thinking'); + const toolCalls = assistantMessage.content.filter((block): block is ToolCall => block.type === 'toolCall'); + const roundContent = textBlocks.map(block => block.text).join(''); + const roundReasoning = thinkingBlocks.map(block => block.thinking).join(''); + + const roundMessageStart = messages.length; + const newRoundStart = newMessages.length; + messages.push(assistantMessage); + newMessages.push(assistantMessage); + if (!toolCalls.length && !roundContent && !roundReasoning) { this.uiRenderer.appendBlock({ type: 'content', markdown: '_Mutsumi Debug: No content, reasoning, or tool calls received from API._' }); await this.session.replaceOutput(JSON.stringify(this.uiRenderer.getCommittedRenderData()), { mimeType: MUTSUMI_AGENT_CHAT_MIME }); - const msg: AgentMessage = { role: 'assistant', content: roundContent }; - if (roundReasoning) { - msg.reasoning_content = roundReasoning; - } - if (replayState) msg.metadata = { ...msg.metadata, piAiReplay: replayState }; - messages.push(msg); - newMessages.push(msg); break; } if (toolCalls.length === 0) { - const assistantMsg: AgentMessage = { role: 'assistant', content: roundContent }; - if (roundReasoning) { - assistantMsg.reasoning_content = roundReasoning; - } - if (replayState) assistantMsg.metadata = { ...assistantMsg.metadata, piAiReplay: replayState }; - messages.push(assistantMsg); - newMessages.push(assistantMsg); break; } - const assistantMsgWithTool: AgentMessage = { - role: 'assistant', - content: roundContent || null, - tool_calls: toolCalls - }; - if (roundReasoning) { - assistantMsgWithTool.reasoning_content = roundReasoning; - } - if (replayState) assistantMsgWithTool.metadata = { ...assistantMsgWithTool.metadata, piAiReplay: replayState }; - messages.push(assistantMsgWithTool); - newMessages.push(assistantMsgWithTool); - this.uiRenderer.commitRoundUI(roundContent, roundReasoning); - const result = await this.toolExecutor.executeTools( - toolCalls, - abortController.signal, - { - appendOutput: async (block: RenderBlock) => { - this.uiRenderer.appendBlock(block); - await this.session.replaceOutput(JSON.stringify(this.uiRenderer.getCommittedRenderData()), { mimeType: MUTSUMI_AGENT_CHAT_MIME }); - }, - signalTermination: () => { - // Termination handled via return values + let result: ToolExecutionResult; + try { + result = await this.toolExecutor.executeTools( + toolCalls, + abortController.signal, + { + appendOutput: async (block: RenderBlock) => { + this.uiRenderer.appendBlock(block); + await this.session.replaceOutput(JSON.stringify(this.uiRenderer.getCommittedRenderData()), { mimeType: MUTSUMI_AGENT_CHAT_MIME }); + }, + signalTermination: () => { + // Termination handled via return values + } } + ); + } catch (error: any) { + // An incomplete tool round cannot be replayed safely. + messages.splice(roundMessageStart); + newMessages.splice(newRoundStart); + if (abortController.signal.aborted || this.session.token.isCancellationRequested + || error?.name === 'AbortError' || error?.name === 'APIUserAbortError') { + status = 'cancelled'; + } else { + status = 'failed'; + failure = { + code: typeof error?.code === 'string' && error.code ? error.code : 'TOOL_EXECUTION_ERROR', + message: error?.message || String(error), + }; + console.error('Tool execution infrastructure error:', error); } - ); + break; + } const toolMessages = result.messages; messages.push(...toolMessages); newMessages.push(...toolMessages); + if (abortController.signal.aborted || this.session.token.isCancellationRequested) { + // A cancelled tool round is not a replayable conversation turn. + messages.splice(roundMessageStart); + newMessages.splice(newRoundStart); + status = 'cancelled'; + break; + } + // Handle task completion (e.g., from task_finish tool) if (result.isTaskComplete) { await this.markSessionAsFinished(); @@ -241,6 +260,20 @@ export class AgentRunner { // Handle other termination cases (e.g., edit rejection) if (result.shouldTerminate) { + status = 'failed'; + failure = { + code: 'TOOL_TERMINATED', + message: 'A tool terminated the agent run before task completion', + }; + break; + } + + if (loopCount >= this.maxLoops) { + status = 'failed'; + failure = { + code: 'MAX_LOOPS_EXCEEDED', + message: `Agent reached the maximum of ${this.maxLoops} tool interaction loops`, + }; break; } } @@ -248,11 +281,15 @@ export class AgentRunner { // Generate title after first user message (only once) // Skip for LiteAgentSession which is used for background tasks like title generation const userMessageCount = messages.filter(m => m.role === 'user').length; - if (userMessageCount === 1 && !(this.session instanceof LiteAgentSession)) { + if (status === 'completed' && userMessageCount === 1 && !(this.session instanceof LiteAgentSession)) { void this.generateTitleIfNeeded(this.session, messages, config); } - return newMessages; + return { + messages: newMessages, + status, + ...(failure ? { error: failure } : {}), + }; } /** diff --git a/src/agent/fileOps.ts b/src/agent/fileOps.ts index 9036068..d9b3931 100644 --- a/src/agent/fileOps.ts +++ b/src/agent/fileOps.ts @@ -7,9 +7,10 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { v4 as uuidv4 } from 'uuid'; import { resolveModelSelection } from '../utils'; -import { AgentStateInfo, ContextItem, ModelSelection } from '../types'; +import { AgentContext, AgentMessage, AgentStateInfo, ContextItem, ModelSelection, MTM_FORMAT_VERSION } from '../types'; import { resolveAgentDefaults } from '../config/resolver'; import { McpRegistry } from '../mcp/registry'; +import { decodeAgentContext, encodeAgentContext } from '../mtmFormat'; /** * Handles file-based operations for agents. @@ -60,7 +61,7 @@ export class AgentFileOperations { const fileUri = agentDir.with({ path: path.posix.join(agentDir.path, name) }); try { const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)); + const data = decodeAgentContext(content); if (data.metadata && data.metadata.uuid) { agents.push({ @@ -101,7 +102,7 @@ export class AgentFileOperations { try { const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)); + const data = decodeAgentContext(content); const agent: AgentStateInfo = { uuid, @@ -184,7 +185,9 @@ export class AgentFileOperations { // Determine name and context based on prompt const hasPrompt = prompt && prompt.trim().length > 0; const agentName = hasPrompt ? prompt!.slice(0, 20) + '...' : 'New Agent'; - const context = hasPrompt ? [{ role: 'user', content: prompt }] : []; + const context: AgentMessage[] = hasPrompt + ? [{ role: 'user', content: prompt!, timestamp: Date.now() }] + : []; // Inject ROLE macro based on agentType (user could override later) contextItems = contextItems ?? []; @@ -194,7 +197,8 @@ export class AgentFileOperations { content: agentType }); - const content: any = { + const content: AgentContext = { + formatVersion: MTM_FORMAT_VERSION, metadata: { uuid: uuid, name: agentName, @@ -214,7 +218,7 @@ export class AgentFileOperations { context: context }; - const encoded = new TextEncoder().encode(JSON.stringify(content, null, 2)); + const encoded = encodeAgentContext(content); await vscode.workspace.fs.writeFile(fileUri, encoded); return fileUri; @@ -256,11 +260,11 @@ export class AgentFileOperations { } else { // Document not open, write directly to file const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)); + const data = decodeAgentContext(content); data.metadata.parent_agent_id = newParentId; - const encoded = new TextEncoder().encode(JSON.stringify(data, null, 2)); + const encoded = encodeAgentContext(data); await vscode.workspace.fs.writeFile(fileUri, encoded); } return true; @@ -303,12 +307,12 @@ export class AgentFileOperations { await vscode.workspace.applyEdit(edit); } else { const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)); + const data = decodeAgentContext(content); data.metadata.model = resolved.model; data.metadata.provider = resolved.provider; - const encoded = new TextEncoder().encode(JSON.stringify(data, null, 2)); + const encoded = encodeAgentContext(data); await vscode.workspace.fs.writeFile(fileUri, encoded); } } @@ -345,11 +349,11 @@ export class AgentFileOperations { } else { // Document not open, write directly to file const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)); + const data = decodeAgentContext(content); data.metadata.sub_agents_list = Array.from(parent.childIds || []); - const encoded = new TextEncoder().encode(JSON.stringify(data, null, 2)); + const encoded = encodeAgentContext(data); await vscode.workspace.fs.writeFile(fileUri, encoded); } return true; @@ -380,11 +384,7 @@ export class AgentFileOperations { try { // Read file content const content = await vscode.workspace.fs.readFile(uri); - const data = JSON.parse(new TextDecoder().decode(content)); - - if (!data.metadata) { - throw new Error(`Invalid mtm file: missing metadata`); - } + const data = decodeAgentContext(content); // Generate new UUID const newUuid = uuidv4(); @@ -398,7 +398,7 @@ export class AgentFileOperations { data.metadata.created_at = new Date().toISOString(); // Write back to file - const encoded = new TextEncoder().encode(JSON.stringify(data, null, 2)); + const encoded = encodeAgentContext(data); await vscode.workspace.fs.writeFile(uri, encoded); return { newUuid, newMetadata: data.metadata }; diff --git a/src/agent/llmClient.ts b/src/agent/llmClient.ts index c8be134..e2f3272 100644 --- a/src/agent/llmClient.ts +++ b/src/agent/llmClient.ts @@ -1,12 +1,15 @@ -/** Provider-neutral LLM client backed by pi-ai's multi-protocol catalog. */ +/** Provider-neutral LLM client backed directly by pi-ai's native Context and events. */ -import type { AssistantMessage, SimpleStreamOptions, ThinkingLevel } from '@earendil-works/pi-ai'; +import type { + AssistantMessage, + AssistantMessageEvent, + SimpleStreamOptions, + ThinkingLevel, +} from '@earendil-works/pi-ai'; import type { AgentMessage } from '../types'; import type { ToolDefinition } from '../tools.d/interface'; import { toPiContext } from '../llm/context'; import { LlmProviderService } from '../llm/providerService'; -import { toReplayState } from '../llm/replay'; -import type { PiAiReplayState } from '../llm/types'; export interface LLMClientConfig { provider: string; @@ -15,52 +18,15 @@ export interface LLMClientConfig { } export interface ChatCompletionOptions { + systemPrompt?: string; messages: AgentMessage[]; tools?: ToolDefinition[]; - tool_choice?: 'auto' | 'none' | { type: 'function'; function: { name: string } }; temperature?: number; - max_tokens?: number; + maxTokens?: number; signal?: AbortSignal; } -export interface ChatCompletionResult { - content: string | null; - reasoning_content?: string; - tool_calls?: any[]; - replayState?: PiAiReplayState; - usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number }; -} - -export interface StreamChunk { - content?: string; - reasoning_content?: string; - tool_calls?: any[]; - replayState?: PiAiReplayState; - done: boolean; -} - -function visibleParts(message: AssistantMessage): Omit { - const texts: string[] = []; - const reasoning: string[] = []; - const toolCalls: any[] = []; - for (const block of message.content) { - if (block.type === 'text') texts.push(block.text); - else if (block.type === 'thinking') reasoning.push(block.thinking); - else toolCalls.push({ - id: block.id, - type: 'function', - function: { name: block.name, arguments: JSON.stringify(block.arguments) }, - }); - } - return { - content: texts.join('') || null, - ...(reasoning.length > 0 ? { reasoning_content: reasoning.join('') } : {}), - ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}), - replayState: toReplayState(message), - }; -} - -/** Unified LLM client whose provider identity is frozen for each request. */ +/** One request is frozen to a provider registry snapshot and returns native pi-ai messages. */ export class LLMClient { private model: string; private readonly provider: string; @@ -72,91 +38,28 @@ export class LLMClient { this.reasoningEffort = config.reasoningEffort; } - async chatCompletion(options: ChatCompletionOptions): Promise { + async chatCompletion(options: ChatCompletionOptions): Promise { const prepared = LlmProviderService.getInstance().prepare(this.provider, this.model); const result = await prepared.models.completeSimple( prepared.model, - toPiContext(options.messages, options.tools), + toPiContext(options.systemPrompt, options.messages, options.tools), this.streamOptions(options), ); - if (result.stopReason === 'error' || result.stopReason === 'aborted') { - throw this.providerError(result); - } - return { - ...visibleParts(result), - usage: { - prompt_tokens: result.usage.input, - completion_tokens: result.usage.output, - total_tokens: result.usage.totalTokens, - }, - }; + if (result.stopReason === 'error' || result.stopReason === 'aborted') throw this.providerError(result); + return result; } - async *streamChatCompletion(options: ChatCompletionOptions): AsyncIterableIterator { + async *streamChatCompletion(options: ChatCompletionOptions): AsyncIterableIterator { const prepared = LlmProviderService.getInstance().prepare(this.provider, this.model); const events = prepared.models.streamSimple( prepared.model, - toPiContext(options.messages, options.tools), + toPiContext(options.systemPrompt, options.messages, options.tools), this.streamOptions(options), ); - const toolArgumentDeltas = new Set(); for await (const event of events) { - switch (event.type) { - case 'text_delta': - yield { content: event.delta, done: false }; - break; - case 'thinking_delta': - yield { reasoning_content: event.delta, done: false }; - break; - case 'toolcall_start': { - const block = event.partial.content[event.contentIndex]; - if (block?.type === 'toolCall') { - yield { - tool_calls: [{ - index: event.contentIndex, - id: block.id, - type: 'function', - function: { name: block.name, arguments: '' }, - }], - done: false, - }; - } - break; - } - case 'toolcall_delta': - toolArgumentDeltas.add(event.contentIndex); - yield { - tool_calls: [{ - index: event.contentIndex, - function: { arguments: event.delta }, - }], - done: false, - }; - break; - case 'toolcall_end': - if (!toolArgumentDeltas.has(event.contentIndex)) { - yield { - tool_calls: [{ - index: event.contentIndex, - id: event.toolCall.id, - type: 'function', - function: { - name: event.toolCall.name, - arguments: JSON.stringify(event.toolCall.arguments), - }, - }], - done: false, - }; - } - break; - case 'done': - yield { replayState: toReplayState(event.message), done: true }; - return; - case 'error': - throw this.providerError(event.error); - default: - break; - } + if (event.type === 'error') throw this.providerError(event.error); + yield event; + if (event.type === 'done') return; } throw new Error('Provider stream ended without a terminal event'); } @@ -172,13 +75,11 @@ export class LLMClient { private streamOptions(options: ChatCompletionOptions): SimpleStreamOptions { const raw = this.reasoningEffort === 'none' ? 'off' : this.reasoningEffort; const allowed = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']; - if (raw !== undefined && !allowed.includes(raw)) { - throw new Error(`Unsupported reasoning effort "${raw}"`); - } + if (raw !== undefined && !allowed.includes(raw)) throw new Error(`Unsupported reasoning effort "${raw}"`); return { ...(raw === undefined ? {} : { reasoning: raw as ThinkingLevel }), ...(options.temperature === undefined ? {} : { temperature: options.temperature }), - ...(options.max_tokens === undefined ? {} : { maxTokens: options.max_tokens }), + ...(options.maxTokens === undefined ? {} : { maxTokens: options.maxTokens }), ...(options.signal === undefined ? {} : { signal: options.signal }), maxRetries: 0, }; diff --git a/src/agent/llmStream.ts b/src/agent/llmStream.ts index 572005e..b9c7b1b 100644 --- a/src/agent/llmStream.ts +++ b/src/agent/llmStream.ts @@ -1,228 +1,93 @@ -/** - * @fileoverview LLM Stream Handler for processing streaming responses using LLMClient. - * @module llmStream - */ +/** Streaming UI projection over pi-ai's native assistant-message event protocol. */ -import { LLMClient, StreamChunk } from './llmClient'; -import type { PiAiReplayState } from '../llm/types'; +import type { AssistantMessage, ToolCall } from '@earendil-works/pi-ai'; +import { LLMClient } from './llmClient'; +import type { ToolDefinition } from '../tools.d/interface'; +import type { AgentMessage } from '../types'; -/** - * Callback function type for streaming progress updates. - * @callback StreamProgressCallback - * @param {string} content - Accumulated content from the stream - * @param {string} reasoning - Accumulated reasoning content from the stream - * @param {any[]} [toolCalls] - Accumulated raw tool calls (may be partial/incomplete) - */ -export type StreamProgressCallback = (content: string, reasoning: string, toolCalls?: any[]) => void; +export type StreamProgressCallback = ( + content: string, + reasoning: string, + toolCalls?: ToolCall[], +) => void | Promise; -/** - * Result of a streaming response operation. - * @interface StreamResponseResult - */ export interface StreamResponseResult { - /** Accumulated content from the LLM response */ - roundContent: string; - /** Accumulated reasoning content (e.g., from DeepSeek reasoning models) */ - roundReasoning: string; - /** Parsed tool calls from the response */ - toolCalls: any[]; - /** Provider-native state required to safely replay this assistant turn */ - replayState?: PiAiReplayState; + message: AssistantMessage; } -/** - * Checks if an error is retryable (network-related). - * @param {any} error - The error to check - * @returns {boolean} True if the error is retryable - * @example - * if (isRetryableError(error)) { - * await retryWithBackoff(); - * } - */ -function isRetryableError(error: any): boolean { - if (!error) return false; - - const errorMessage = error.message || error.toString(); - const retryablePatterns = [ - 'ECONNRESET', - 'ETIMEDOUT', - 'ECONNREFUSED', - 'ENOTFOUND', - 'EAI_AGAIN', - 'socket hang up', - 'network timeout', - 'failed to fetch', - 'disconnected', - 'network error', - 'aborted' // Only when not user-initiated - ]; - - return retryablePatterns.some(pattern => - errorMessage.toLowerCase().includes(pattern.toLowerCase()) - ); +function visible(message: AssistantMessage): { content: string; reasoning: string; toolCalls: ToolCall[] } { + const content: string[] = []; + const reasoning: string[] = []; + const toolCalls: ToolCall[] = []; + for (const block of message.content) { + if (block.type === 'text') content.push(block.text); + else if (block.type === 'thinking') reasoning.push(block.thinking); + else toolCalls.push(block); + } + return { content: content.join(''), reasoning: reasoning.join(''), toolCalls }; +} + +function isRetryableError(error: unknown): boolean { + const message = error instanceof Error ? error.message : String(error); + return [ + 'ECONNRESET', 'ETIMEDOUT', 'ECONNREFUSED', 'ENOTFOUND', 'EAI_AGAIN', + 'socket hang up', 'network timeout', 'failed to fetch', 'disconnected', 'network error', + ].some(pattern => message.toLowerCase().includes(pattern.toLowerCase())); } -/** - * Delays execution for the specified milliseconds. - * @param {number} ms - Milliseconds to delay - * @returns {Promise} - * @example - * await delay(1000); // Wait 1 second - */ function delay(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } -/** - * Handles LLM streaming responses and tool call parsing. - * @description Manages the streaming interaction with LLM via LLMClient, - * collecting content, reasoning content, and tool calls from the stream. - * Includes exponential backoff retry logic for network failures. - * @class LLMStreamHandler - * @example - * const handler = new LLMStreamHandler(llmClient); - * const result = await handler.streamResponse(messages, tools, signal, (content, reasoning) => { - * console.log('Progress:', content); - * }); - */ export class LLMStreamHandler { - /** Maximum number of retry attempts for failed requests */ private readonly maxRetries = 3; - /** Base delay in milliseconds for exponential backoff (1s, 2s, 4s) */ private readonly baseDelayMs = 1000; - /** - * Creates a new LLMStreamHandler instance. - * @constructor - * @param {LLMClient} llmClient - LLM client instance for making API calls - */ - constructor(private llmClient: LLMClient) {} + constructor(private readonly llmClient: LLMClient) {} - /** - * Streams the LLM response and collects content, reasoning, and tool calls. - * @description Runs the conversation loop with the LLM, handling streaming, - * retries with exponential backoff for network errors, and result collection. - * @param {any[]} messages - Current message history - * @param {any[]} tools - Tool definitions to provide to the LLM - * @param {AbortSignal} signal - Abort signal for cancellation - * @param {StreamProgressCallback} [onProgress] - Optional callback for progress updates - * @returns {Promise} Object containing roundContent, roundReasoning, and toolCalls - * @throws {Error} If the API call fails after all retries or is aborted - * @example - * const result = await handler.streamResponse( - * messages, - * toolDefinitions, - * abortController.signal, - * (content, reasoning) => updateUI(content, reasoning) - * ); - */ async streamResponse( - messages: any[], - tools: any[], + systemPrompt: string | undefined, + messages: AgentMessage[], + tools: ToolDefinition[], signal: AbortSignal, - onProgress?: StreamProgressCallback + onProgress?: StreamProgressCallback, ): Promise { let attempt = 0; - while (attempt <= this.maxRetries) { try { - return await this.doStreamResponse(messages, tools, signal, onProgress); + return await this.doStreamResponse(systemPrompt, messages, tools, signal, onProgress); } catch (error) { - // Don't retry if user aborted - if (signal.aborted) { - throw error; - } - - // Check if this is a retryable error + if (signal.aborted) throw error; if (isRetryableError(error) && !(error as any)?.mutsumiPartialOutput && attempt < this.maxRetries) { attempt++; - const delayMs = this.baseDelayMs * Math.pow(2, attempt - 1); - console.warn(`LLM stream failed, retrying (${attempt}/${this.maxRetries}) after ${delayMs}ms...`, error); - await delay(delayMs); + await delay(this.baseDelayMs * Math.pow(2, attempt - 1)); continue; } - - // Not retryable or max retries exceeded throw error; } } - throw new Error('Max retries exceeded for LLM stream request'); } - /** - * Performs the actual streaming request. - * @private - * @param {any[]} messages - Current message history - * @param {any[]} tools - Tool definitions to provide to the LLM - * @param {AbortSignal} signal - Abort signal for cancellation - * @param {StreamProgressCallback} [onProgress] - Optional callback for progress updates - * @returns {Promise} Object containing roundContent, roundReasoning, and toolCalls - * @throws {Error} If the API call fails or is aborted - */ private async doStreamResponse( - messages: any[], - tools: any[], + systemPrompt: string | undefined, + messages: AgentMessage[], + tools: ToolDefinition[], signal: AbortSignal, - onProgress?: StreamProgressCallback + onProgress?: StreamProgressCallback, ): Promise { - const stream = this.llmClient.streamChatCompletion({ - messages, - tools, - tool_choice: 'auto', - signal - }); - - let currentRoundContent = ''; - let currentReasoningContent = ''; - let replayState: PiAiReplayState | undefined; - const toolCallBuffers: { [index: number]: any } = {}; + let emittedPartial = false; try { - for await (const chunk of stream) { - if (signal.aborted) { - break; - } - - let progressUpdateNeeded = false; - - if (chunk.replayState) replayState = chunk.replayState; - - // Accumulate reasoning content - if (chunk.reasoning_content) { - currentReasoningContent += chunk.reasoning_content; - progressUpdateNeeded = true; - } - - // Accumulate regular content - if (chunk.content) { - currentRoundContent += chunk.content; - progressUpdateNeeded = true; - } - - // Buffer tool calls from the stream - if (chunk.tool_calls) { - for (const tc of chunk.tool_calls) { - const idx = tc.index ?? 0; - if (!toolCallBuffers[idx]) { - toolCallBuffers[idx] = { ...tc, arguments: '' }; - } - if (tc.function?.name) { - toolCallBuffers[idx].function.name = tc.function.name; - } - if (tc.function?.arguments) { - toolCallBuffers[idx].function.arguments += tc.function.arguments; - } - } - progressUpdateNeeded = true; - } - - // Call progress callback if provided and update is needed - if (progressUpdateNeeded && onProgress) { - onProgress(currentRoundContent, currentReasoningContent, Object.values(toolCallBuffers)); - } + for await (const event of this.llmClient.streamChatCompletion({ systemPrompt, messages, tools, signal })) { + if (event.type === 'done') return { message: event.message }; + if (event.type === 'error') throw new Error(event.error.errorMessage ?? 'Provider stream failed'); + const partial = event.partial; + const projected = visible(partial); + emittedPartial ||= projected.content.length > 0 || projected.reasoning.length > 0 || projected.toolCalls.length > 0; + if (onProgress) await onProgress(projected.content, projected.reasoning, projected.toolCalls); } } catch (error) { - if (currentRoundContent || currentReasoningContent || Object.keys(toolCallBuffers).length > 0) { + if (emittedPartial) { const marked = error instanceof Error && Object.isExtensible(error) ? error : new Error(error instanceof Error ? error.message : String(error), { cause: error }); @@ -231,71 +96,6 @@ export class LLMStreamHandler { } throw error; } - - const rawToolCalls = Object.values(toolCallBuffers); - const finalToolCalls = this.parseToolCalls(rawToolCalls); - - return { - roundContent: currentRoundContent, - roundReasoning: currentReasoningContent, - toolCalls: finalToolCalls, - ...(replayState ? { replayState } : {}) - }; - } - - /** - * Parses raw tool calls from the stream into structured format. - * @description Handles JSON parsing of tool arguments, including error recovery - * for malformed JSON and deduplication of repeated arguments. - * @param {any[]} rawToolCalls - Raw tool call data from stream - * @returns {any[]} Parsed tool calls with proper structure - * @example - * const toolCalls = handler.parseToolCalls(rawToolCalls); - * // Returns: [{ id: 'call_xxx', type: 'function', function: { name: 'toolName', arguments: '{}' } }] - */ - parseToolCalls(rawToolCalls: any[]): any[] { - const finalToolCalls: any[] = []; - - for (const tc of rawToolCalls) { - const toolName = tc.function.name; - const toolArgsStr = tc.function.arguments; - let argsArray: any[] = []; - - try { - // Try to parse as single object first - const parsed = JSON.parse(toolArgsStr); - argsArray = [parsed]; - } catch (e) { - // If single parse fails, try to fix and parse as array - try { - const fixedStr = '[' + toolArgsStr.replace(/}\s*{/g, '},{') + ']'; - const parsedArr = JSON.parse(fixedStr); - if (Array.isArray(parsedArr) && parsedArr.length > 0) { - // Deduplicate arguments - const uniqueArgs = new Set(parsedArr.map(x => JSON.stringify(x))); - argsArray = Array.from(uniqueArgs).map(x => JSON.parse(x)); - } else { - throw e; - } - } catch (e2) { - console.error(`JSON Parse Error for tool ${toolName}:`, toolArgsStr); - continue; - } - } - - // Create a tool call entry for each argument set - argsArray.forEach((args, i) => { - const callId = (i === 0 && tc.id) ? tc.id : 'call_' + Math.random().toString(36).substring(2, 11); - finalToolCalls.push({ - id: callId, - type: 'function', - function: { - name: toolName, - arguments: JSON.stringify(args) - } - }); - }); - } - return finalToolCalls; + throw new Error('Provider stream ended without a terminal event'); } } diff --git a/src/agent/titleGenerator.ts b/src/agent/titleGenerator.ts index b922c11..fe86958 100644 --- a/src/agent/titleGenerator.ts +++ b/src/agent/titleGenerator.ts @@ -12,6 +12,10 @@ import { LiteAdapter } from '../adapters/liteAdapter'; import { createEmptyToolSet } from '../tools.d/toolManager'; import { getTitleModelSelection, resolveModelSelection } from '../utils'; import type { AgentRunOptions } from './types'; +import type { AgentRunContext } from './types'; +import { assistantText, messageText } from '../llm/messageText'; +import { parsePersistedInteraction } from '../mtmFormat'; +import { hydrateProviderMessage } from '../contextManagement/history'; /** * Creates a deep clone of an object. @@ -48,9 +52,8 @@ export function sanitizeFileName(name: string): string { * @param {AgentMessage[]} messages - Conversation message history * @returns {AgentMessage[]} Messages for title generation prompt */ -function createTitleGenerationMessages(messages: AgentMessage[]): AgentMessage[] { - // Filter out system messages and split into rounds - const dialogMessages = messages.filter(msg => msg.role !== 'system'); +function createTitleGenerationMessages(messages: AgentMessage[]): AgentRunContext { + const dialogMessages = messages; const rounds: AgentMessage[][] = []; let currentRound: AgentMessage[] = []; @@ -72,22 +75,22 @@ function createTitleGenerationMessages(messages: AgentMessage[]): AgentMessage[] // Take last 6 rounds const recentRounds = rounds.length <= 6 ? rounds : rounds.slice(-6); const contextMessages = recentRounds.flat(); - const contextJson = JSON.stringify(contextMessages, null, 2); + const visibleConversation = contextMessages + .map(message => `${message.role}: ${messageText(message)}`) + .join('\n\n'); - return [ - { - role: 'system', - content: 'Please generate a short title based on the following conversation content. ' + + return { + systemPrompt: 'Please generate a short title based on the following conversation content. ' + 'The title should summarize the main topic of the conversation. ' + - 'Conversation data is provided in JSON format, containing messages from user, assistant, tool roles. ' + + 'Conversation data contains visible text from user, assistant, and toolResult messages. ' + 'Requirements:\n1. Length should be 10-20 characters\n2. No special characters like \\\/:*?"<>|' + - '\n3. Return only the title text, no explanations or prefixes' - }, - { + '\n3. Return only the title text, no explanations or prefixes', + messages: [{ role: 'user', - content: `Please generate a title for this conversation:\n\n${contextJson.substring(0, 4000)}` - } - ]; + content: `Please generate a title for this conversation:\n\n${visibleConversation.substring(0, 4000)}`, + timestamp: Date.now(), + }], + }; } /** @@ -134,13 +137,16 @@ export async function generateTitle( // Run the agent (will be single round since no tools) const abortController = new AbortController(); - const newMessages = await runner.run(abortController, titleMessages); + const runResult = await runner.run(abortController, titleMessages); + if (runResult.status !== 'completed') { + throw new Error(runResult.error?.message ?? 'Title generation was cancelled'); + } // The last assistant message contains the title - const lastAssistantMsg = [...newMessages].reverse().find(m => m.role === 'assistant'); + const lastAssistantMsg = [...runResult.messages].reverse().find(m => m.role === 'assistant'); let title = 'New Agent'; - if (lastAssistantMsg?.content && typeof lastAssistantMsg.content === 'string') { - title = lastAssistantMsg.content.trim(); + if (lastAssistantMsg) { + title = assistantText(lastAssistantMsg).trim(); } // Sanitize the title @@ -162,10 +168,9 @@ export function extractMessagesFromNotebook(notebook: vscode.NotebookDocument): const messages: AgentMessage[] = []; for (const cell of notebook.getCells()) { if (cell.kind === vscode.NotebookCellKind.Code) { - messages.push({ role: 'user', content: cell.document.getText() }); - if (cell.metadata?.mutsumi_interaction) { - messages.push(...(cell.metadata.mutsumi_interaction as AgentMessage[])); - } + messages.push({ role: 'user', content: cell.document.getText(), timestamp: Number(cell.metadata?.timestamp) || 0 }); + const interaction = parsePersistedInteraction(cell.metadata?.mutsumi_interaction); + if (interaction) messages.push(...interaction.map(hydrateProviderMessage)); } } return messages; diff --git a/src/agent/toolExecutor.ts b/src/agent/toolExecutor.ts index 9ec06d3..8a0c3ed 100644 --- a/src/agent/toolExecutor.ts +++ b/src/agent/toolExecutor.ts @@ -11,6 +11,7 @@ import type { UIRenderer } from "./uiRenderer"; import type { RenderBlock } from "../notebook/renderTypes"; import type { IAgentSession } from "../adapters/interfaces"; import { getCachedResult, setCachedResult } from "../tools.d/cache"; +import type { ToolCall } from '@earendil-works/pi-ai'; /** Race a thenable against an abort signal; rejects when the signal fires. */ function raceAbort(signal: AbortSignal, p: Thenable): Promise { @@ -101,7 +102,7 @@ export class ToolExecutor { * }); */ async executeTools( - toolCalls: any[], + toolCalls: ToolCall[], abortSignal: AbortSignal, callbacks: ToolExecutorCallbacks, ): Promise { @@ -114,21 +115,8 @@ export class ToolExecutor { break; } - const toolName = tc.function.name; - const toolArgsStr = tc.function.arguments; - let toolArgs: any; - try { - toolArgs = JSON.parse(toolArgsStr); - } catch (err: any) { - toolMessages.push({ - role: "tool", - tool_call_id: tc.id, - name: toolName, - content: `Error: invalid tool arguments JSON: ${err.message}`, - metadata: { isError: true }, - }); - continue; - } + const toolName = tc.name; + const toolArgs = tc.arguments; const toolSession = new ToolSession(this.session.id, toolName); const onAgentAbort = () => toolSession.abort(); @@ -206,11 +194,12 @@ export class ToolExecutor { ); toolMessages.push({ - role: "tool", - tool_call_id: tc.id, - name: toolName, - content: toolResult, - metadata: { isError }, + role: "toolResult", + toolCallId: tc.id, + toolName, + content: [{ type: 'text', text: toolResult }], + isError, + timestamp: Date.now(), }); } return { messages: toolMessages, shouldTerminate, isTaskComplete }; diff --git a/src/agent/types.ts b/src/agent/types.ts index 3578983..aa13439 100644 --- a/src/agent/types.ts +++ b/src/agent/types.ts @@ -4,6 +4,7 @@ */ import type { AgentStateInfo, AgentRuntimeStatus } from '../types'; +import type { AgentMessage } from '../types'; // Re-export imported types export type { AgentStateInfo, AgentRuntimeStatus }; @@ -74,3 +75,23 @@ export interface DispatchSession { /** Set of child agent UUIDs that have been deleted */ deletedChildren: Set; } + +/** Provider-ready conversation state; system instructions are not persisted as messages. */ +export interface AgentRunContext { + systemPrompt?: string; + messages: AgentMessage[]; +} + +export type AgentRunStatus = 'completed' | 'failed' | 'cancelled'; + +export interface AgentRunFailure { + code: string; + message: string; +} + +/** Outcome of one run. Only native messages in this result may be persisted. */ +export interface AgentRunResult { + messages: AgentMessage[]; + status: AgentRunStatus; + error?: AgentRunFailure; +} diff --git a/src/agent/uiRenderer.ts b/src/agent/uiRenderer.ts index a17370a..9dfc562 100644 --- a/src/agent/uiRenderer.ts +++ b/src/agent/uiRenderer.ts @@ -6,8 +6,8 @@ */ import { RenderBlock, RenderData } from '../notebook/renderTypes'; -import { tryParsePartialJson } from './utils'; import type { ToolSet } from '../tools.d/toolManager'; +import type { ToolCall } from '@earendil-works/pi-ai'; /** * Accumulates agent output as structured render blocks. @@ -150,7 +150,7 @@ export class UIRenderer { * @returns {RenderBlock[]} Pending tool call blocks */ formatPendingToolCalls( - partialToolCalls: any[] | undefined, + partialToolCalls: ToolCall[] | undefined, toolSet: ToolSet, _isSubAgent?: boolean ): RenderBlock[] { @@ -159,9 +159,9 @@ export class UIRenderer { } const blocks: RenderBlock[] = []; for (const ptc of partialToolCalls) { - const toolName = ptc.function?.name; + const toolName = ptc.name; if (!toolName) { continue; } - const args = tryParsePartialJson(ptc.function?.arguments); + const args = ptc.arguments ?? {}; const summary = toolSet.getPrettyPrint(toolName, args); const config = toolSet.getRenderingConfig(toolName); blocks.push(this.formatToolCall(toolName, args, summary, true, undefined, config)); diff --git a/src/contextManagement/history.ts b/src/contextManagement/history.ts index feee476..eec3496 100644 --- a/src/contextManagement/history.ts +++ b/src/contextManagement/history.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; -import { AgentMessage, AgentMetadata, MessageContent, ContextItem } from '../types'; +import type { Usage } from '@earendil-works/pi-ai'; +import { AgentMessage, AgentMetadata, ContextItem, PersistedAgentMessage } from '../types'; import { IAgentSession } from '../adapters/interfaces'; import { getSystemPrompt, getRulesContext } from './prompts'; import { TemplateEngine } from './templateEngine'; @@ -16,6 +17,86 @@ import { computeHash } from './utils'; +const ZERO_USAGE: Usage = { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + totalTokens: 0, + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, +}; + +function finiteNumber(value: unknown): value is number { + return typeof value === 'number' && Number.isFinite(value); +} + +function validUsage(value: unknown): value is Usage { + if (!value || typeof value !== 'object' || Array.isArray(value)) return false; + const usage = value as Record; + if (!usage.cost || typeof usage.cost !== 'object' || Array.isArray(usage.cost)) return false; + const cost = usage.cost as Record; + return ['input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens'].every(key => finiteNumber(usage[key])) + && (usage.cacheWrite1h === undefined || finiteNumber(usage.cacheWrite1h)) + && (usage.reasoning === undefined || finiteNumber(usage.reasoning)) + && ['input', 'output', 'cacheRead', 'cacheWrite', 'total'].every(key => finiteNumber(cost[key])); +} + +/** Create the strict temporary message shape required by pi-ai without changing disk data. */ +export function hydrateProviderMessage(message: PersistedAgentMessage): AgentMessage { + if (message.role === 'user') { + return { + ...message, + timestamp: finiteNumber(message.timestamp) ? message.timestamp : 0, + } as AgentMessage; + } + if (message.role === 'assistant') { + const stopReasons = new Set(['stop', 'length', 'toolUse', 'error', 'aborted']); + const inferredStopReason = message.content.some(block => block.type === 'toolCall') ? 'toolUse' : 'stop'; + return { + ...message, + usage: validUsage(message.usage) ? message.usage : { ...ZERO_USAGE, cost: { ...ZERO_USAGE.cost } }, + timestamp: finiteNumber(message.timestamp) ? message.timestamp : 0, + stopReason: typeof message.stopReason === 'string' && stopReasons.has(message.stopReason) + ? message.stopReason + : inferredStopReason, + } as AgentMessage; + } + return { + ...message, + usage: validUsage(message.usage) ? message.usage : { ...ZERO_USAGE, cost: { ...ZERO_USAGE.cost } }, + timestamp: finiteNumber(message.timestamp) ? message.timestamp : 0, + } as AgentMessage; +} + +function userContentParts(content: Extract['content']) { + return typeof content === 'string' ? [{ type: 'text' as const, text: content }] : [...content]; +} + +/** Merge pending adjacent user turns only at the provider boundary. */ +export function mergeConsecutiveUserMessages(messages: AgentMessage[]): AgentMessage[] { + const merged: AgentMessage[] = []; + for (const message of messages) { + const previous = merged[merged.length - 1]; + if (message.role !== 'user' || previous?.role !== 'user') { + merged.push(message); + continue; + } + const content = typeof previous.content === 'string' && typeof message.content === 'string' + ? `${previous.content}\n\n${message.content}` + : [ + ...userContentParts(previous.content), + { type: 'text' as const, text: '\n\n' }, + ...userContentParts(message.content), + ]; + merged[merged.length - 1] = { + ...previous, + content, + timestamp: message.timestamp, + }; + } + return merged; +} + /** * @description Build Agent's conversation history context. * Ghost blocks are consumed and persisted as structured GhostBlock objects; @@ -26,10 +107,17 @@ import { */ export async function buildInteractionHistory( session: IAgentSession, - currentPrompt?: string -): Promise<{ messages: AgentMessage[], allowedUris: string[], isSubAgent: boolean }> { + currentPrompt?: string, + baseHistory?: PersistedAgentMessage[], +): Promise<{ + systemPrompt: string; + messages: AgentMessage[]; + persistedMessages: PersistedAgentMessage[]; + allowedUris: string[]; + isSubAgent: boolean; +}> { // Get current prompt from session if not provided - if (!currentPrompt) { + if (currentPrompt === undefined) { currentPrompt = await session.getInput(); } const messages: AgentMessage[] = []; @@ -74,11 +162,6 @@ export async function buildInteractionHistory( systemPromptContent += '\n\n# Installed Skills\n' + skillsMarkdown; } - messages.push({ - role: 'system', - content: systemPromptContent - }); - // Get previous ghost blocks for version tracking const previousGhostBlocks = session.getPreviousGhostBlocks ? await session.getPreviousGhostBlocks() @@ -159,19 +242,18 @@ export async function buildInteractionHistory( newContextItemsForMetadata.push(...macroContextItems); // 3. Build Message History from session - const history = await session.getHistory(); + const history = baseHistory ?? await session.getHistory(); // Track ghost block index separately (only for user messages) let ghostBlockIndex = 0; - // Process raw history - expand interactions and attach ghost blocks - // NOTE: mutsumi_interaction ONLY exists on user messages, containing the - // assistant and tool messages that followed that user prompt + // Project persisted ghost blocks into provider-facing user content. The + // session already returns canonical, expanded pi-ai messages. for (const msg of history) { if (msg.role === 'user') { - const multiModalContent = await parseUserMessageWithImages( - typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content) - ); + const multiModalContent = typeof msg.content === 'string' + ? await parseUserMessageWithImages(msg.content) + : [...msg.content]; // Append the persisted ghost block if it exists const savedGhostBlock = previousGhostBlocks[ghostBlockIndex] ?? null; ghostBlockIndex++; @@ -181,30 +263,23 @@ export async function buildInteractionHistory( if (savedGhostMarkdown) { if (Array.isArray(multiModalContent)) { - messages.push({ role: 'user', content: [...multiModalContent, { type: 'text', text: savedGhostMarkdown }] }); + messages.push(hydrateProviderMessage({ + role: 'user', + content: [...multiModalContent, { type: 'text', text: savedGhostMarkdown }], + timestamp: msg.timestamp, + })); } else { - messages.push({ role: 'user', content: multiModalContent + savedGhostMarkdown }); + messages.push(hydrateProviderMessage({ + role: 'user', + content: multiModalContent + savedGhostMarkdown, + timestamp: msg.timestamp, + })); } } else { - messages.push({ role: 'user', content: multiModalContent }); - } - - // Expand mutsumi_interaction from user message metadata - // This contains the assistant response and any tool calls/results - const interaction = msg.metadata?.mutsumi_interaction as AgentMessage[] | undefined; - if (interaction && Array.isArray(interaction)) { - messages.push(...interaction); + messages.push(hydrateProviderMessage({ role: 'user', content: multiModalContent, timestamp: msg.timestamp })); } - } else if (msg.role === 'assistant') { - // Assistant messages in history are standalone (orphan messages without a preceding user) - // or legacy format. Add them directly. - messages.push(msg); - } else if (msg.role === 'system') { - // Skip, we already added system prompt - continue; } else { - // tool, etc. - add directly - messages.push(msg); + messages.push(hydrateProviderMessage(msg)); } } @@ -224,17 +299,28 @@ export async function buildInteractionHistory( } // 6. Push final message + const currentTimestamp = Date.now(); + const persistedMessages: PersistedAgentMessage[] = [ + ...history, + { role: 'user', content: currentPrompt, timestamp: currentTimestamp }, + ]; const currentMultiModalContent = await parseUserMessageWithImages(processedPrompt); if (currentGhostMarkdown) { if (Array.isArray(currentMultiModalContent)) { currentMultiModalContent.push({ type: 'text', text: currentGhostMarkdown }); - messages.push({ role: 'user', content: currentMultiModalContent }); + messages.push({ role: 'user', content: currentMultiModalContent, timestamp: currentTimestamp }); } else { - messages.push({ role: 'user', content: currentMultiModalContent + currentGhostMarkdown }); + messages.push({ role: 'user', content: currentMultiModalContent + currentGhostMarkdown, timestamp: currentTimestamp }); } } else { - messages.push({ role: 'user', content: currentMultiModalContent }); + messages.push({ role: 'user', content: currentMultiModalContent, timestamp: currentTimestamp }); } - return { messages, allowedUris, isSubAgent }; + return { + systemPrompt: systemPromptContent, + messages: mergeConsecutiveUserMessages(messages), + persistedMessages, + allowedUris, + isSubAgent, + }; } diff --git a/src/contextManagement/templateEngine.ts b/src/contextManagement/templateEngine.ts index 14f5afb..8f72748 100644 --- a/src/contextManagement/templateEngine.ts +++ b/src/contextManagement/templateEngine.ts @@ -1,5 +1,12 @@ import * as vscode from 'vscode'; -import * as pp from 'preprocess'; +const pp = require('preprocess') as { + preprocess(source: string, context?: Record, options?: { + fileNotFoundSilentFail?: boolean; + srcDir?: string; + srcEol?: string; + type?: string; + }): string; +}; import { extractBracketContent, parseReference, diff --git a/src/contextManagement/utils.ts b/src/contextManagement/utils.ts index 63f9fbf..4f461fe 100644 --- a/src/contextManagement/utils.ts +++ b/src/contextManagement/utils.ts @@ -34,6 +34,9 @@ export async function readImageAsBase64( ): Promise { try { const uri = vscode.Uri.parse(uriStr); + if (uri.scheme === "data") { + return uriStr; + } if (uri.scheme !== "file") { if (uri.scheme === "http" || uri.scheme === "https") { return uriStr; @@ -85,13 +88,12 @@ export async function parseUserMessageWithImages( try { const imageBase64 = await readImageAsBase64(uriStr); - if (imageBase64) { + const match = imageBase64?.match(/^data:([^;,]+);base64,(.+)$/s); + if (match) { content.push({ - type: "image_url", - image_url: { - url: imageBase64, - detail: "auto", - }, + type: "image", + mimeType: match[1], + data: match[2], }); } else { content.push({ type: "text", text: fullMatch }); diff --git a/src/controller.ts b/src/controller.ts index 707be57..6b6ae07 100644 --- a/src/controller.ts +++ b/src/controller.ts @@ -85,7 +85,7 @@ export class AgentController { const reasoningEffort = normalizeReasoningEffort(notebook.metadata?.reasoning_effort); // Resolve model selection from metadata: complete pair → use; missing model → global default; - // model without provider → migration error. + // model without provider → invalid current-format metadata. let model: string; let provider: string; try { @@ -158,17 +158,17 @@ export class AgentController { session ); - const { messages: history } = await buildInteractionHistory(session); - const newMessages = await runner.run(abortController, history); + const history = await buildInteractionHistory(session); + const runResult = await runner.run(abortController, { + systemPrompt: history.systemPrompt, + messages: history.messages, + }); - if (newMessages.length > 0) { - // Update session history and persist - // This delegates metadata updates (both Cell and Notebook) to the adapter - session.setHistory([...history, ...newMessages]); - await session.save(); - } + // Persist the user turn, context metadata, and only fully formed native messages. + session.setHistory([...history.persistedMessages, ...runResult.messages]); + await session.save(); - (session as any).end(true); + (session as any).end(runResult.status === 'completed'); } catch (err: any) { const isCancellation = err.name === 'APIUserAbortError' || diff --git a/src/extension.ts b/src/extension.ts index 377ec53..a6271b7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -38,7 +38,6 @@ import { AgentTypeRegistry } from "./registry/agentTypeRegistry"; import { resolveAgentDefaults, getEntryAgentTypes } from "./config/resolver"; import { McpRegistry } from "./mcp/registry"; import { LlmProviderService } from "./llm/providerService"; -import { registerLegacyProviderMigration } from "./llm/migration"; /** * Checks if a file exists at the given URI. @@ -109,7 +108,6 @@ export async function activate( // Provider catalogs and SecretStorage must exist before model defaults are resolved. const llmProviderService = LlmProviderService.getInstance(); await llmProviderService.initialize(context); - registerLegacyProviderMigration(context); // Validate configuration before changing either runtime registry, then connect MCP // servers before agent creation can consume their discovery snapshots. diff --git a/src/httpServer/agent.ts b/src/httpServer/agent.ts index 4af3544..25a040f 100644 --- a/src/httpServer/agent.ts +++ b/src/httpServer/agent.ts @@ -2,7 +2,8 @@ import * as vscode from 'vscode'; import * as express from 'express'; import { getAgentFromRegistry } from './utils'; import { AgentOrchestrator } from '../agent/agentOrchestrator'; -import type { AgentMessage, AgentContext } from '../types'; +import type { PersistedAgentMessage } from '../types'; +import { decodeAgentContext, isMtmFormatError } from '../mtmFormat'; /** * Handle GET /agent/:uuid - Get agent details with full history @@ -24,16 +25,17 @@ export async function handleGetAgent(req: express.Request, res: express.Response // Load full history from file const fileUri = vscode.Uri.parse(agent.fileUri); - let history: AgentMessage[] = []; + let history: PersistedAgentMessage[] = []; if (fileUri) { try { const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)) as AgentContext; - if (Array.isArray(data.context)) { - history = data.context; + history = decodeAgentContext(content).context; + } catch (error) { + if (isMtmFormatError(error)) { + res.status(422).json({ status: 'error', code: error.code, content: error.message }); + return; } - } catch { - // Ignore, return empty history + throw error; } } diff --git a/src/httpServer/agents.ts b/src/httpServer/agents.ts index 9ff5652..9d23a44 100644 --- a/src/httpServer/agents.ts +++ b/src/httpServer/agents.ts @@ -9,6 +9,7 @@ import { MutsumiSerializer } from '../notebook/serializer'; import { resolveAgentDefaults, validateEntryAgentType } from '../config/resolver'; import type { AgentContext, AgentMetadata } from '../types'; import { McpRegistry } from '../mcp/registry'; +import { decodeAgentContext } from '../mtmFormat'; export interface CreateAgentDependencies { extensionUri: vscode.Uri; @@ -99,7 +100,7 @@ export function createCreateAgentHandler( // Register the agent in the registry // Parse metadata from the generated content to ensure consistency - const agentContext = JSON.parse(new TextDecoder().decode(initialContent)) as AgentContext; + const agentContext = decodeAgentContext(initialContent); await AgentOrchestrator.getInstance().notifyNotebookDocumentOpened(uuid, newFileUri, agentContext.metadata); res.status(201).json({ diff --git a/src/httpServer/chat.ts b/src/httpServer/chat.ts index b5a05a8..0ddfbea 100644 --- a/src/httpServer/chat.ts +++ b/src/httpServer/chat.ts @@ -13,7 +13,9 @@ import { } from '../agent/types'; import type { HeadlessAdapter } from '../adapters/headlessAdapter'; import type { AgentSessionConfig } from '../adapters/interfaces'; -import type { AgentMessage, AgentMetadata, ModelSelection } from '../types'; +import type { AgentMetadata, ModelSelection } from '../types'; +import { buildInteractionHistory } from '../contextManagement/history'; +import { isMtmFormatError } from '../mtmFormat'; export async function handleChat( req: express.Request, @@ -68,7 +70,16 @@ export async function handleChat( const serializer = new MutsumiSerializer(); const tokenSource = new vscode.CancellationTokenSource(); - const notebookData = await serializer.deserializeNotebook(content, tokenSource.token); + let notebookData: vscode.NotebookData; + try { + notebookData = await serializer.deserializeNotebook(content, tokenSource.token); + } catch (error) { + if (isMtmFormatError(error)) { + res.status(422).json({ status: 'error', code: error.code, content: error.message }); + return; + } + throw error; + } // Get VS Code configuration const config = vscode.workspace.getConfiguration('mutsumi'); @@ -94,7 +105,7 @@ export async function handleChat( if (hasModel && hasProvider) { effectiveSelection = resolveModelSelection({ model, provider }); } else { - // Use persisted pair. Missing model → global default; model without provider → migration error. + // Use persisted pair. Missing model → global default; model without provider is invalid. if (!metadataModel) { effectiveSelection = getDefaultModelSelection(); } else if (!metadataProvider) { @@ -123,6 +134,10 @@ export async function handleChat( try { await AgentFileOperations.updateAgentModelSelection(fileUri, effectiveSelection); } catch (err: any) { + if (isMtmFormatError(err)) { + res.status(422).json({ status: 'error', code: err.code, content: err.message }); + return; + } res.status(400).json({ status: 'error', content: err.message }); return; } @@ -194,31 +209,12 @@ export async function handleChat( // Set the input prompt (session as any).setInput(prompt); - // Append user message to history - const userMessage: AgentMessage = { role: 'user', content: prompt }; + const baseHistory = await session.getHistory(); + const runHistory = await buildInteractionHistory(session, prompt, baseHistory); - // Get existing history and append new user message - const history = await session.getHistory(); - history.push(userMessage); - - // Serialize updated history back to file (persist user message) - const userCell = new vscode.NotebookCellData( - vscode.NotebookCellKind.Code, - prompt, - 'markdown' - ); - userCell.metadata = { role: 'user' }; - const notebookDataWithUser = new vscode.NotebookData([ - ...notebookData.cells, - userCell - ]); - notebookData.metadata = updatedMetadata; - notebookDataWithUser.metadata = updatedMetadata; - const encoded = await serializer.serializeNotebook(notebookDataWithUser, tokenSource.token); - await vscode.workspace.fs.writeFile(fileUri, encoded); - - // Update session history - (session as any).setHistory(history); + // Persist the pending turn before the potentially long-running provider call. + session.setHistory(runHistory.persistedMessages); + await session.save(); // Create AgentRunner options const runnerOptions = { @@ -278,23 +274,32 @@ export async function handleChat( // Run the agent and stream results try { const runner = new AgentRunner(runnerOptions, toolSet, session); - const newMessages = await runner.run(abortController, history); - - // Update session with new history - const updatedHistory = [...history, ...newMessages]; - (session as any).setHistory(updatedHistory); + const runResult = await runner.run(abortController, { + systemPrompt: runHistory.systemPrompt, + messages: runHistory.messages, + }); + + // Persist the unanswered user turn and any fully completed native rounds. + const updatedHistory = [...runHistory.persistedMessages, ...runResult.messages]; + session.setHistory(updatedHistory); + await session.save(); isFinished = true; - // Send final event - const finalEvent = { - type: 'done', - messageCount: newMessages.length - }; + const finalEvent = runResult.status === 'failed' + ? { + type: 'error', + code: runResult.error?.code ?? 'AGENT_RUN_FAILED', + error: runResult.error?.message ?? 'Agent execution failed', + messageCount: runResult.messages.length, + } + : runResult.status === 'cancelled' + ? { type: 'cancelled', messageCount: runResult.messages.length } + : { type: 'done', messageCount: runResult.messages.length }; res.write(`data: ${JSON.stringify(finalEvent)}\n\n`); res.end(); - console.log(`[Mutsumi] Agent ${uuid} streaming completed with ${newMessages.length} new messages`); + console.log(`[Mutsumi] Agent ${uuid} streaming ${runResult.status} with ${runResult.messages.length} new messages`); } catch (error: any) { console.error(`[Mutsumi] Agent ${uuid} streaming error:`, error); isFinished = true; @@ -307,14 +312,7 @@ export async function handleChat( res.write(`data: ${JSON.stringify(errorEvent)}\n\n`); res.end(); - // Append error as assistant message - const errorMessage: AgentMessage = { - role: 'assistant', - content: `> ⚠️ **Error**: ${error.message || String(error)}\n\n*Execution failed.*` - }; - const errorHistory = [...history, errorMessage]; - (session as any).setHistory(errorHistory); - await session.save(); + // Incomplete/error assistant messages are never synthesized or persisted. } finally { abortControllers.delete(uuid); // Restore original method @@ -325,26 +323,25 @@ export async function handleChat( void (async () => { try { const runner = new AgentRunner(runnerOptions, toolSet, session!); - const newMessages = await runner.run(abortController, history); - - // Update session with new history - const updatedHistory = [...history, ...newMessages]; - (session as any).setHistory(updatedHistory); - - console.log(`[Mutsumi] Agent ${uuid} completed with ${newMessages.length} new messages`); + const runResult = await runner.run(abortController, { + systemPrompt: runHistory.systemPrompt, + messages: runHistory.messages, + }); + + // Persist only fully completed native messages, regardless of final run status. + const updatedHistory = [...runHistory.persistedMessages, ...runResult.messages]; + session.setHistory(updatedHistory); + await session.save(); + + if (runResult.status === 'failed') { + console.error(`[Mutsumi] Agent ${uuid} failed: ${runResult.error?.message ?? 'Unknown error'}`); + } else { + console.log(`[Mutsumi] Agent ${uuid} ${runResult.status} with ${runResult.messages.length} new messages`); + } } catch (error: any) { console.error(`[Mutsumi] Agent ${uuid} error:`, error); - // Append error as assistant message - const errorMessage: AgentMessage = { - role: 'assistant', - content: `> ⚠️ **Error**: ${error.message || String(error)}\n\n*Execution failed.*` - }; - const errorHistory = [...history, errorMessage]; - (session as any).setHistory(errorHistory); - - // Persist error to file - await session!.save(); + // Incomplete/error assistant messages are never synthesized or persisted. } finally { abortControllers.delete(uuid); } diff --git a/src/httpServer/rules.ts b/src/httpServer/rules.ts index 4e76a79..2502ea9 100644 --- a/src/httpServer/rules.ts +++ b/src/httpServer/rules.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; import type { Request, Response } from 'express'; import { getWorkspaceRoot, getAvailableRules, getAgentFromRegistry } from './utils'; -import type { AgentContext } from '../types'; +import { decodeAgentContext, encodeAgentContext, isMtmFormatError } from '../mtmFormat'; /** * GET /rules - Get all available rule filenames @@ -119,13 +119,13 @@ export async function handleSetRules(req: Request, res: Response): Promise try { // Read current content const content = await vscode.workspace.fs.readFile(fileUri); - const data = JSON.parse(new TextDecoder().decode(content)) as AgentContext; + const data = decodeAgentContext(content); // Update activeRules in metadata data.metadata.activeRules = rules; // Write back - const encoded = new TextEncoder().encode(JSON.stringify(data, null, 2)); + const encoded = encodeAgentContext(data); await vscode.workspace.fs.writeFile(fileUri, encoded); res.json({ @@ -137,6 +137,10 @@ export async function handleSetRules(req: Request, res: Response): Promise }); } catch (error: any) { console.error('Failed to set rules:', error); + if (isMtmFormatError(error)) { + res.status(422).json({ status: 'error', code: error.code, content: error.message }); + return; + } res.status(500).json({ status: 'error', content: `Failed to set rules: ${error.message}` }); } } diff --git a/src/llm/context.ts b/src/llm/context.ts index 537ee70..0e25a6d 100644 --- a/src/llm/context.ts +++ b/src/llm/context.ts @@ -1,76 +1,26 @@ -import type { Context, ImageContent, Message, TextContent, Tool } from '@earendil-works/pi-ai'; -import type { AgentMessage, MessageContent } from '../types'; -import { toPiAssistant } from './replay'; +import type { Context, Message, Tool } from '@earendil-works/pi-ai'; +import type { AgentMessage } from '../types'; +import type { ToolDefinition } from '../tools.d/interface'; -interface OpenAiToolDefinition { - type: 'function'; - function: { name: string; description?: string; parameters?: Record }; -} - -function decodeDataUrl(url: string): ImageContent { - const match = /^data:([^;,]+);base64,(.+)$/s.exec(url); - if (!match) throw new Error('Only base64 data URLs can be sent as image content'); - return { type: 'image', mimeType: match[1], data: match[2] }; -} - -function userContent(content: MessageContent | null): string | (TextContent | ImageContent)[] { - if (content === null || typeof content === 'string') return content ?? ''; - const parts: (TextContent | ImageContent)[] = []; - for (const part of content) { - if (part.type === 'text') { - if (part.text) parts.push({ type: 'text', text: part.text }); - } else { - parts.push(decodeDataUrl(part.image_url.url)); - } - } - return parts.every(part => part.type === 'text') - ? parts.map(part => (part as TextContent).text).join('') - : parts; -} - -function textContent(content: MessageContent | null): string { - if (content === null) return ''; - if (typeof content === 'string') return content; - return content.filter(part => part.type === 'text').map(part => part.text).join(''); -} - -/** Convert Mutsumi's durable history and OpenAI-shaped tool schemas into pi-ai Context. */ -export function toPiContext(messages: AgentMessage[], tools: OpenAiToolDefinition[] = []): Context { - const converted: Message[] = []; - const leadingSystem: string[] = []; - let sawConversation = false; - for (const message of messages) { - if (message.role === 'system' && !sawConversation) { - leadingSystem.push(textContent(message.content)); - continue; - } - sawConversation = true; - if (message.role === 'system') { - converted.push({ role: 'user', content: textContent(message.content), timestamp: 0 }); - } else if (message.role === 'user') { - converted.push({ role: 'user', content: userContent(message.content), timestamp: 0 }); - } else if (message.role === 'assistant') { - converted.push(toPiAssistant(message)); - } else { - converted.push({ - role: 'toolResult', - toolCallId: message.tool_call_id ?? '', - toolName: message.name ?? 'unknown', - content: [{ type: 'text', text: textContent(message.content) || '(no output)' }], - isError: message.metadata?.isError === true - || /^(?:Error:|\[Interrupted\])/.test(textContent(message.content)), - timestamp: 0, - }); - } - } +/** Build the exact pi-ai request context without translating message formats. */ +export function toPiContext( + systemPrompt: string | undefined, + messages: AgentMessage[], + tools: ToolDefinition[] = [], +): Context { + const nativeMessages: Message[] = messages.map(message => { + if (message.role !== 'user' || message.mutsumi === undefined) return message; + const { mutsumi: _mutsumi, ...native } = message; + return native; + }); const piTools: Tool[] = tools.map(tool => ({ name: tool.function.name, description: tool.function.description ?? '', parameters: (tool.function.parameters ?? { type: 'object', properties: {} }) as Tool['parameters'], })); return { - ...(leadingSystem.length > 0 ? { systemPrompt: leadingSystem.join('\n\n') } : {}), - messages: converted, + ...(systemPrompt ? { systemPrompt } : {}), + messages: nativeMessages, ...(piTools.length > 0 ? { tools: piTools } : {}), }; } diff --git a/src/llm/credentialStore.ts b/src/llm/credentialStore.ts index af3c8b1..c0cf991 100644 --- a/src/llm/credentialStore.ts +++ b/src/llm/credentialStore.ts @@ -57,7 +57,7 @@ export class VsCodeCredentialStore implements CredentialStore { }); } - /** Store a legacy API key without ever projecting it into ordinary settings. */ + /** Store an API key without ever projecting it into ordinary settings. */ async storeApiKey(providerId: string, key: string): Promise { await this.modify(providerId, async current => ({ type: 'api_key', diff --git a/src/llm/messageText.ts b/src/llm/messageText.ts new file mode 100644 index 0000000..854b2b3 --- /dev/null +++ b/src/llm/messageText.ts @@ -0,0 +1,21 @@ +import type { AssistantMessage, Message } from '@earendil-works/pi-ai'; + +/** Visible textual projection used by titles, compression, debug output, and rendering. */ +export function messageText(message: Message): string { + if (message.role === 'user') { + if (typeof message.content === 'string') return message.content; + return message.content.map(part => part.type === 'text' ? part.text : `[Image: ${part.mimeType}]`).join(''); + } + if (message.role === 'assistant') { + return message.content.map(block => { + if (block.type === 'text') return block.text; + if (block.type === 'thinking') return block.thinking; + return `[Tool Call: ${block.name}]`; + }).join(''); + } + return message.content.map(part => part.type === 'text' ? part.text : `[Image: ${part.mimeType}]`).join(''); +} + +export function assistantText(message: AssistantMessage): string { + return message.content.filter(block => block.type === 'text').map(block => block.text).join(''); +} diff --git a/src/llm/migration.ts b/src/llm/migration.ts deleted file mode 100644 index 187fe96..0000000 --- a/src/llm/migration.ts +++ /dev/null @@ -1,165 +0,0 @@ -import * as vscode from 'vscode'; -import { t } from '../i18n'; -import { LlmProviderService } from './providerService'; -import type { CustomProviderProfile } from './types'; - -interface LegacyProvider { - name: string; - baseurl: string; - api_key?: string; -} - -interface Layer { - target: vscode.ConfigurationTarget; - resource?: vscode.Uri; - providers: LegacyProvider[]; - models: Record; - customProviders: Record; -} - -const PROMPTED_KEY = 'mutsumi.legacyCredentialMigration.prompted.v1'; -const DEFAULT_KIMI_URL = 'https://api.kimi.com/coding/v1'; - -function inspectLayers(resource?: vscode.Uri, includeShared = true): Layer[] { - const config = vscode.workspace.getConfiguration('mutsumi', resource); - const providers = config.inspect('providers'); - const models = config.inspect>('models'); - const custom = config.inspect>('customProviders'); - const layers: Layer[] = []; - const add = ( - target: vscode.ConfigurationTarget, - providerValue: LegacyProvider[] | undefined, - modelValue: Record | undefined, - customValue: Record | undefined, - ) => { - if (Array.isArray(providerValue) && providerValue.length > 0) { - layers.push({ target, resource, providers: providerValue, models: modelValue ?? {}, customProviders: customValue ?? {} }); - } - }; - if (includeShared) { - add(vscode.ConfigurationTarget.Global, providers?.globalValue, models?.globalValue, custom?.globalValue); - add(vscode.ConfigurationTarget.Workspace, providers?.workspaceValue, models?.workspaceValue, custom?.workspaceValue); - } - add(vscode.ConfigurationTarget.WorkspaceFolder, providers?.workspaceFolderValue, models?.workspaceFolderValue, custom?.workspaceFolderValue); - return layers; -} - -function allLayers(): Layer[] { - const layers = inspectLayers(undefined, true).filter(layer => layer.target !== vscode.ConfigurationTarget.WorkspaceFolder); - for (const folder of vscode.workspace.workspaceFolders ?? []) { - layers.push(...inspectLayers(folder.uri, false)); - } - return layers; -} - -function secretConflicts(layers: Layer[]): string[] { - const keys = new Map>(); - for (const layer of layers) for (const provider of layer.providers) { - if (!provider.api_key) continue; - const route = provider.name === 'kimi-for-coding' && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL - ? 'kimi-coding' - : provider.name; - const values = keys.get(route) ?? new Set(); - values.add(provider.api_key); - keys.set(route, values); - } - return [...keys].filter(([, values]) => values.size > 1).map(([route]) => route); -} - -/** Move legacy plaintext provider credentials into SecretStorage, then remove their settings. */ -export async function migrateLegacyProviders(): Promise { - const layers = allLayers(); - if (layers.length === 0) return false; - const conflicts = secretConflicts(layers); - if (conflicts.length > 0) { - throw new Error(t('migration.conflicts', conflicts.join(', '))); - } - - const service = LlmProviderService.getInstance(); - const reservedLegacyRoutes = layers.flatMap(layer => layer.providers).filter(provider => { - const isDefaultKimi = provider.name === 'kimi-for-coding' - && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL; - return !isDefaultKimi && service.isBuiltInProviderId(provider.name); - }).map(provider => provider.name); - if (reservedLegacyRoutes.length > 0) { - throw new Error(t('migration.routeConflicts', [...new Set(reservedLegacyRoutes)].join(', '))); - } - const credentials = service.getCredentialStore(); - // Store every secret first. Configuration remains untouched if any secure write fails. - for (const layer of layers) for (const provider of layer.providers) { - if (!provider.api_key) continue; - const isDefaultKimi = provider.name === 'kimi-for-coding' - && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL; - await credentials.storeApiKey(isDefaultKimi ? 'kimi-coding' : provider.name, provider.api_key); - } - - const migratedCustom = new Map>(); - for (const layer of layers) { - const customProviders = { ...layer.customProviders }; - for (const provider of layer.providers) { - const isDefaultKimi = provider.name === 'kimi-for-coding' - && provider.baseurl.replace(/\/+$/, '') === DEFAULT_KIMI_URL; - if (isDefaultKimi) continue; - customProviders[provider.name] = { - displayName: provider.name, - baseUrl: provider.baseurl, - api: 'openai-completions', - auth: 'apiKey', - models: layer.models[provider.name] ?? [], - }; - } - migratedCustom.set(layer, customProviders); - } - - // Finish every non-secret write before removing any legacy value. - for (const [layer, customProviders] of migratedCustom) { - await vscode.workspace.getConfiguration('mutsumi', layer.resource) - .update('customProviders', customProviders, layer.target); - } - - const cleared: Layer[] = []; - try { - for (const layer of layers) { - const config = vscode.workspace.getConfiguration('mutsumi', layer.resource); - cleared.push(layer); - await config.update('providers', undefined, layer.target); - await config.update('models', undefined, layer.target); - } - } catch (error) { - // Best-effort rollback ensures a partial settings failure does not silently discard secrets. - for (const layer of cleared.reverse()) { - const config = vscode.workspace.getConfiguration('mutsumi', layer.resource); - try { await config.update('providers', layer.providers, layer.target); } catch { /* best effort */ } - try { await config.update('models', layer.models, layer.target); } catch { /* best effort */ } - } - throw error; - } - await service.reload(); - void vscode.window.showWarningMessage( - t('migration.rotationWarning'), - ); - return true; -} - -/** Register the manual migration command and show the one-time activation prompt. */ -export function registerLegacyProviderMigration(context: vscode.ExtensionContext): void { - const run = async () => { - try { - const migrated = await migrateLegacyProviders(); - if (!migrated) void vscode.window.showInformationMessage(t('migration.noneFound')); - } catch (error: any) { - void vscode.window.showErrorMessage(t('migration.failed', error.message ?? String(error))); - } - }; - context.subscriptions.push(vscode.commands.registerCommand('mutsumi.migrateProviderCredentials', run)); - if (allLayers().length === 0 - || context.globalState.get(PROMPTED_KEY, false)) return; - void context.globalState.update(PROMPTED_KEY, true).then(async () => { - const migrate = t('migration.action'); - const selected = await vscode.window.showWarningMessage( - t('migration.prompt'), - migrate, - ); - if (selected === migrate) await run(); - }); -} diff --git a/src/llm/providerService.ts b/src/llm/providerService.ts index e1a0a9f..d5602c6 100644 --- a/src/llm/providerService.ts +++ b/src/llm/providerService.ts @@ -26,9 +26,7 @@ const DEFAULT_CONTEXT_WINDOW = 262_144; const DEFAULT_MAX_TOKENS = 32_768; const DISCOVERY_LIMIT = 4 * 1024 * 1024; const DISCOVERY_TIMEOUT_MS = 15_000; -const LEGACY_PROVIDER_ALIASES: Readonly> = { - 'kimi-for-coding': 'kimi-coding', -}; +const REMOVED_PROVIDER_IDS = new Set(['kimi-for-coding']); const NO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }; interface Snapshot { @@ -84,9 +82,8 @@ export class LlmProviderService { models.setProvider(provider); } for (const [id, profile] of customProfiles) { - if (providers.has(id) || LEGACY_PROVIDER_ALIASES[id]) { - throw new Error(`Custom provider "${id}" conflicts with a built-in provider`); - } + if (providers.has(id)) throw new Error(`Custom provider "${id}" conflicts with a built-in provider`); + if (REMOVED_PROVIDER_IDS.has(id)) throw new Error(`Custom provider "${id}" uses a removed provider ID`); const provider = this.createCustomProvider(id, profile); providers.set(id, provider); models.setProvider(provider); @@ -96,12 +93,8 @@ export class LlmProviderService { this.snapshot = { models, providers, customProfiles }; } - canonicalProvider(provider: string): string { - return LEGACY_PROVIDER_ALIASES[provider] ?? provider; - } - resolveSelection(selection: ModelSelection): ModelSelection & { modelInfo: ModelInfo } { - const provider = this.canonicalProvider(selection.provider.trim()); + const provider = selection.provider.trim(); const model = selection.model.trim(); if (!provider || !model) throw new Error('Model and provider must be non-empty strings'); const resolved = this.requireSnapshot().models.getModel(provider, model); @@ -110,19 +103,17 @@ export class LlmProviderService { } getModel(provider: string, model: string): Model { - const canonical = this.canonicalProvider(provider); - const resolved = this.requireSnapshot().models.getModel(canonical, model); - if (!resolved) throw new Error(`Model "${model}" is not available from provider "${canonical}"`); + const resolved = this.requireSnapshot().models.getModel(provider, model); + if (!resolved) throw new Error(`Model "${model}" is not available from provider "${provider}"`); return resolved; } /** Capture the registry and model used by one request so config reloads cannot split it. */ prepare(provider: string, model: string): { models: Models; model: Model; provider: string } { const snapshot = this.requireSnapshot(); - const canonical = this.canonicalProvider(provider); - const resolved = snapshot.models.getModel(canonical, model); - if (!resolved) throw new Error(`Model "${model}" is not available from provider "${canonical}"`); - return { models: snapshot.models, model: resolved, provider: canonical }; + const resolved = snapshot.models.getModel(provider, model); + if (!resolved) throw new Error(`Model "${model}" is not available from provider "${provider}"`); + return { models: snapshot.models, model: resolved, provider }; } async listProviders(): Promise { @@ -179,28 +170,26 @@ export class LlmProviderService { listModels(provider: string): ModelInfo[] { return this.requireSnapshot().models - .getModels(this.canonicalProvider(provider)) + .getModels(provider) .map(model => this.toModelInfo(model)); } isBuiltInProviderId(provider: string): boolean { - const canonical = this.canonicalProvider(provider); const snapshot = this.requireSnapshot(); - return snapshot.providers.has(canonical) && !snapshot.customProfiles.has(canonical); + return snapshot.providers.has(provider) && !snapshot.customProfiles.has(provider); } async configureApiKey(provider: string, interaction: AuthInteraction): Promise { - const canonical = this.canonicalProvider(provider); const snapshot = this.requireSnapshot(); - const entry = snapshot.providers.get(canonical); - if (!entry?.auth.apiKey?.login) throw new Error(`Provider "${canonical}" does not support API-key setup`); - await snapshot.models.login(canonical, 'api_key', interaction); - if (entry.refreshModels) return (await this.refreshModels()).get(canonical); + const entry = snapshot.providers.get(provider); + if (!entry?.auth.apiKey?.login) throw new Error(`Provider "${provider}" does not support API-key setup`); + await snapshot.models.login(provider, 'api_key', interaction); + if (entry.refreshModels) return (await this.refreshModels()).get(provider); return undefined; } async deleteCredential(provider: string): Promise { - await this.requireSnapshot().models.logout(this.canonicalProvider(provider)); + await this.requireSnapshot().models.logout(provider); } async refreshModels(): Promise> { @@ -209,7 +198,7 @@ export class LlmProviderService { } async deleteCachedModels(provider: string): Promise { - await this.requireModelsStore().delete(this.canonicalProvider(provider)); + await this.requireModelsStore().delete(provider); } getCredentialStore(): VsCodeCredentialStore { diff --git a/src/llm/replay.ts b/src/llm/replay.ts deleted file mode 100644 index 3e1f288..0000000 --- a/src/llm/replay.ts +++ /dev/null @@ -1,169 +0,0 @@ -import type { Api, AssistantMessage, ToolCall, Usage } from '@earendil-works/pi-ai'; -import type { AgentMessage } from '../types'; -import type { PiAiReplayBlock, PiAiReplayState } from './types'; - -function emptyUsage(): Usage { - return { - input: 0, - output: 0, - cacheRead: 0, - cacheWrite: 0, - totalTokens: 0, - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, - }; -} - -function parseArguments(raw: unknown): Record { - if (typeof raw !== 'string') return {}; - try { - const value: unknown = JSON.parse(raw); - return value && typeof value === 'object' && !Array.isArray(value) - ? value as Record - : {}; - } catch { - return {}; - } -} - -/** Project the successful native response into JSON-safe durable replay metadata. */ -export function toReplayState(message: AssistantMessage): PiAiReplayState { - return { - kind: 'pi-ai', - version: 1, - api: message.api, - provider: message.provider, - model: message.model, - ...(message.responseModel === undefined ? {} : { responseModel: message.responseModel }), - ...(message.responseId === undefined ? {} : { responseId: message.responseId }), - stopReason: message.stopReason, - blocks: message.content.map((block): PiAiReplayBlock => { - switch (block.type) { - case 'text': return { - type: 'text', - text: block.text, - ...(block.textSignature === undefined ? {} : { textSignature: block.textSignature }), - }; - case 'thinking': return { - type: 'reasoning', - text: block.thinking, - ...(block.thinkingSignature === undefined ? {} : { thinkingSignature: block.thinkingSignature }), - ...(block.redacted === undefined ? {} : { redacted: block.redacted }), - }; - case 'toolCall': return { - type: 'tool-call', - id: block.id, - name: block.name, - arguments: block.arguments, - ...(block.thoughtSignature === undefined ? {} : { thoughtSignature: block.thoughtSignature }), - }; - } - }), - }; -} - -function visibleText(message: AgentMessage): string { - if (typeof message.content === 'string') return message.content; - if (!Array.isArray(message.content)) return ''; - return message.content.filter(part => part.type === 'text').map(part => part.text).join(''); -} - -function stateMatchesVisible(message: AgentMessage, state: PiAiReplayState): boolean { - const text = state.blocks.filter(block => block.type === 'text').map(block => block.text).join(''); - const reasoning = state.blocks.filter(block => block.type === 'reasoning').map(block => block.text).join(''); - const tools = state.blocks.filter((block): block is Extract => block.type === 'tool-call'); - if (text !== visibleText(message) || reasoning !== (message.reasoning_content ?? '')) return false; - const visibleTools = message.tool_calls ?? []; - if (tools.length !== visibleTools.length) return false; - return tools.every((tool, index) => { - const visible = visibleTools[index]; - return visible?.id === tool.id - && visible?.function?.name === tool.name - && JSON.stringify(parseArguments(visible?.function?.arguments)) === JSON.stringify(tool.arguments); - }); -} - -function readReplayState(message: AgentMessage): PiAiReplayState | undefined { - const value: unknown = message.metadata?.piAiReplay; - if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined; - const state = value as Partial; - if (state.kind !== 'pi-ai' || state.version !== 1) return undefined; - if (typeof state.api !== 'string' || typeof state.provider !== 'string' || typeof state.model !== 'string') return undefined; - if (!Array.isArray(state.blocks)) return undefined; - const validBlocks = state.blocks.every(block => { - if (!block || typeof block !== 'object') return false; - if (block.type === 'text' || block.type === 'reasoning') return typeof block.text === 'string'; - return block.type === 'tool-call' - && typeof block.id === 'string' - && typeof block.name === 'string' - && !!block.arguments - && typeof block.arguments === 'object' - && !Array.isArray(block.arguments); - }); - if (!validBlocks || !stateMatchesVisible(message, state as PiAiReplayState)) return undefined; - return state as PiAiReplayState; -} - -function replayedAssistant(state: PiAiReplayState): AssistantMessage { - return { - role: 'assistant', - api: state.api, - provider: state.provider, - model: state.model, - ...(state.responseModel === undefined ? {} : { responseModel: state.responseModel }), - ...(state.responseId === undefined ? {} : { responseId: state.responseId }), - stopReason: state.stopReason, - usage: emptyUsage(), - timestamp: 0, - content: state.blocks.map(block => { - switch (block.type) { - case 'text': return { - type: 'text' as const, - text: block.text, - ...(block.textSignature === undefined ? {} : { textSignature: block.textSignature }), - }; - case 'reasoning': return { - type: 'thinking' as const, - thinking: block.text, - ...(block.thinkingSignature === undefined ? {} : { thinkingSignature: block.thinkingSignature }), - ...(block.redacted === undefined ? {} : { redacted: block.redacted }), - }; - case 'tool-call': return { - type: 'toolCall' as const, - id: block.id, - name: block.name, - arguments: block.arguments, - ...(block.thoughtSignature === undefined ? {} : { thoughtSignature: block.thoughtSignature }), - }; - } - }), - }; -} - -/** Reconstruct a native assistant turn, trusting replay metadata only when visible data still matches. */ -export function toPiAssistant(message: AgentMessage): AssistantMessage { - const state = readReplayState(message); - if (state) return replayedAssistant(state); - const content: AssistantMessage['content'] = []; - if (message.reasoning_content) content.push({ type: 'thinking', thinking: message.reasoning_content }); - const text = visibleText(message); - if (text) content.push({ type: 'text', text }); - for (const raw of message.tool_calls ?? []) { - const tool: ToolCall = { - type: 'toolCall', - id: typeof raw?.id === 'string' ? raw.id : '', - name: typeof raw?.function?.name === 'string' ? raw.function.name : '', - arguments: parseArguments(raw?.function?.arguments), - }; - content.push(tool); - } - return { - role: 'assistant', - content, - api: 'mutsumi-foreign' as Api, - provider: 'mutsumi-foreign', - model: 'mutsumi-foreign', - usage: emptyUsage(), - stopReason: (message.tool_calls?.length ?? 0) > 0 ? 'toolUse' : 'stop', - timestamp: 0, - }; -} diff --git a/src/llm/types.ts b/src/llm/types.ts index f90e9f2..3d3a100 100644 --- a/src/llm/types.ts +++ b/src/llm/types.ts @@ -1,5 +1,3 @@ -import type { Api, AssistantMessage } from '@earendil-works/pi-ai'; - /** Non-secret configuration for a user-defined OpenAI-compatible route. */ export interface CustomProviderProfile { displayName?: string; @@ -31,31 +29,3 @@ export interface ModelInfo { maxTokens: number; reasoningEfforts: readonly string[]; } - -export type PiAiReplayBlock = - | { type: 'text'; text: string; textSignature?: string } - | { type: 'reasoning'; text: string; thinkingSignature?: string; redacted?: boolean } - | { type: 'tool-call'; id: string; name: string; arguments: Record; thoughtSignature?: string }; - -/** Versioned provider-native state required for safe multi-turn replay. */ -export interface PiAiReplayState { - kind: 'pi-ai'; - version: 1; - api: Api; - provider: string; - model: string; - responseModel?: string; - responseId?: string; - stopReason: AssistantMessage['stopReason']; - blocks: PiAiReplayBlock[]; -} - -/** Metadata written on tool messages so providers receive correct error semantics. */ -export interface ToolMessageMetadata { - isError?: boolean; -} - -/** Reserved Mutsumi metadata fields used by the LLM adapter. */ -export interface LlmMessageMetadata extends ToolMessageMetadata { - piAiReplay?: PiAiReplayState; -} diff --git a/src/mtmFormat.ts b/src/mtmFormat.ts new file mode 100644 index 0000000..61e3e23 --- /dev/null +++ b/src/mtmFormat.ts @@ -0,0 +1,235 @@ +import type { + ImageContent, + TextContent, + ThinkingContent, + ToolCall, +} from '@earendil-works/pi-ai'; +import { decodeGhostBlock } from './contextManagement/ghostBlocks'; +import { + AgentContext, + AgentMetadata, + MTM_FORMAT_VERSION, + NotebookNote, + PersistedAgentMessage, +} from './types'; + +export const UNSUPPORTED_MTM_FORMAT = 'UNSUPPORTED_MTM_FORMAT'; +export const INVALID_MTM_FILE = 'INVALID_MTM_FILE'; + +export class MtmFormatError extends Error { + constructor( + readonly code: typeof UNSUPPORTED_MTM_FORMAT | typeof INVALID_MTM_FILE, + message: string, + readonly actualVersion?: unknown, + ) { + super(message); + this.name = 'MtmFormatError'; + } +} + +function record(value: unknown): value is Record { + return !!value && typeof value === 'object' && !Array.isArray(value); +} + +function textContent(value: unknown): value is TextContent { + return record(value) + && value.type === 'text' + && typeof value.text === 'string'; +} + +function imageContent(value: unknown): value is ImageContent { + return record(value) + && value.type === 'image' + && typeof value.data === 'string' + && typeof value.mimeType === 'string'; +} + +function thinkingContent(value: unknown): value is ThinkingContent { + return record(value) + && value.type === 'thinking' + && typeof value.thinking === 'string'; +} + +function toolCall(value: unknown): value is ToolCall { + return record(value) + && value.type === 'toolCall' + && typeof value.id === 'string' + && typeof value.name === 'string' + && record(value.arguments); +} + +function stringArray(value: unknown): value is string[] { + return Array.isArray(value) && value.every(item => typeof item === 'string'); +} + +function userMessage(value: unknown): value is PersistedAgentMessage & { role: 'user' } { + if (!record(value)) return false; + const content = value.content; + const validContent = typeof content === 'string' + || (Array.isArray(content) && content.every(part => textContent(part) || imageContent(part))); + if (!validContent) return false; + if (value.mutsumi !== undefined) { + if (!record(value.mutsumi)) return false; + if (value.mutsumi.ghostBlock !== undefined && !decodeGhostBlock(value.mutsumi.ghostBlock)) return false; + } + return true; +} + +function assistantMessage(value: unknown): value is PersistedAgentMessage & { role: 'assistant' } { + if (!record(value)) return false; + return Array.isArray(value.content) + && value.content.every(block => textContent(block) || thinkingContent(block) || toolCall(block)) + && typeof value.api === 'string' + && typeof value.provider === 'string' + && typeof value.model === 'string' + && value.mutsumi === undefined; +} + +function toolResultMessage(value: unknown): value is PersistedAgentMessage & { role: 'toolResult' } { + if (!record(value)) return false; + return typeof value.toolCallId === 'string' + && typeof value.toolName === 'string' + && Array.isArray(value.content) + && value.content.every(part => textContent(part) || imageContent(part)) + && typeof value.isError === 'boolean' + && value.mutsumi === undefined; +} + +function parseMessages(value: unknown): PersistedAgentMessage[] { + if (!Array.isArray(value)) throw invalid('context must be an array'); + const messages: PersistedAgentMessage[] = []; + let sawUser = false; + let lastRole: PersistedAgentMessage['role'] | undefined; + const availableToolCalls = new Map(); + + for (let index = 0; index < value.length; index++) { + const raw = value[index]; + if (!record(raw) || typeof raw.role !== 'string') throw invalid(`context[${index}] is not a message`); + let message: PersistedAgentMessage; + if (raw.role === 'user' && userMessage(raw)) { + if (availableToolCalls.size > 0) { + throw invalid(`context[${index}] has an unexpected user message`); + } + sawUser = true; + message = raw; + } else if (raw.role === 'assistant' && sawUser && assistantMessage(raw)) { + if ((lastRole !== 'user' && lastRole !== 'toolResult') || availableToolCalls.size > 0) { + throw invalid(`context[${index}] has an unexpected assistant message`); + } + for (const block of raw.content) { + if (block.type === 'toolCall') { + if (availableToolCalls.has(block.id)) { + throw invalid(`context[${index}] contains duplicate tool call ID "${block.id}"`); + } + availableToolCalls.set(block.id, block.name); + } + } + message = raw; + } else if (raw.role === 'toolResult' && sawUser && toolResultMessage(raw)) { + if (lastRole !== 'assistant' && lastRole !== 'toolResult') { + throw invalid(`context[${index}] has an unexpected tool result`); + } + const expectedName = availableToolCalls.get(raw.toolCallId); + if (expectedName === undefined || expectedName !== raw.toolName) { + throw invalid(`context[${index}] does not match a preceding tool call`); + } + availableToolCalls.delete(raw.toolCallId); + message = raw; + } else { + throw invalid(`context[${index}] is not a valid pi-ai message or violates turn ordering`); + } + messages.push(message); + lastRole = message.role; + } + if (availableToolCalls.size > 0) throw invalid('context ends before all tool calls have results'); + return messages; +} + +/** + * Validate a notebook cell's interaction metadata without letting malformed UI + * state abort the whole run. An interaction may contain assistant/toolResult + * messages only and must form complete tool rounds. + */ +export function parsePersistedInteraction(value: unknown): PersistedAgentMessage[] | undefined { + if (!Array.isArray(value) || value.some(item => record(item) && item.role === 'user')) return undefined; + try { + const parsed = parseMessages([{ role: 'user', content: '', timestamp: 0 }, ...value]); + return parsed.slice(1); + } catch { + return undefined; + } +} + +function parseNotes(value: unknown, userCount: number): NotebookNote[] | undefined { + if (value === undefined) return undefined; + if (!Array.isArray(value)) throw invalid('notes must be an array'); + const notes: NotebookNote[] = []; + for (let index = 0; index < value.length; index++) { + const item = value[index]; + if (!record(item) + || !Number.isInteger(item.beforeUserIndex) + || (item.beforeUserIndex as number) < 0 + || (item.beforeUserIndex as number) > userCount + || typeof item.markdown !== 'string') { + throw invalid(`notes[${index}] is not a valid notebook note`); + } + notes.push({ beforeUserIndex: item.beforeUserIndex as number, markdown: item.markdown }); + } + return notes.length > 0 ? notes : undefined; +} + +function invalid(detail: string): MtmFormatError { + return new MtmFormatError(INVALID_MTM_FILE, `Invalid .mtm file: ${detail}`); +} + +export function parseAgentContext(value: unknown): AgentContext { + if (!record(value)) throw invalid('root must be an object'); + if (value.formatVersion !== MTM_FORMAT_VERSION) { + throw new MtmFormatError( + UNSUPPORTED_MTM_FORMAT, + `Unsupported .mtm format (expected ${MTM_FORMAT_VERSION}, received ${String(value.formatVersion)}). Migrate this file with the standalone migration tool.`, + value.formatVersion, + ); + } + if (!record(value.metadata)) throw invalid('metadata must be an object'); + const metadata = value.metadata as unknown as AgentMetadata; + if (typeof metadata.uuid !== 'string' || typeof metadata.name !== 'string' + || typeof metadata.created_at !== 'string' || !stringArray(metadata.allowed_uris) + || (metadata.parent_agent_id !== null && typeof metadata.parent_agent_id !== 'string')) { + throw invalid('metadata is missing required fields'); + } + if ((metadata.model === undefined) !== (metadata.provider === undefined) + || (metadata.model !== undefined && typeof metadata.model !== 'string') + || (metadata.provider !== undefined && typeof metadata.provider !== 'string')) { + throw invalid('metadata model and provider must be a complete string pair'); + } + if (metadata.provider === 'kimi-for-coding') throw invalid('metadata uses the removed provider ID "kimi-for-coding"'); + const context = parseMessages(value.context); + for (const message of context) { + if (message.role === 'assistant' && message.provider === 'kimi-for-coding') { + throw invalid('assistant message uses the removed provider ID "kimi-for-coding"'); + } + } + const notes = parseNotes(value.notes, context.filter(message => message.role === 'user').length); + return { formatVersion: MTM_FORMAT_VERSION, metadata, context, ...(notes ? { notes } : {}) }; +} + +export function decodeAgentContext(content: Uint8Array): AgentContext { + let value: unknown; + try { + value = JSON.parse(new TextDecoder().decode(content)); + } catch (error) { + const wrapped = new MtmFormatError(INVALID_MTM_FILE, 'Invalid .mtm file: content is not valid JSON'); + (wrapped as Error & { cause?: unknown }).cause = error; + throw wrapped; + } + return parseAgentContext(value); +} + +export function encodeAgentContext(context: AgentContext): Uint8Array { + return new TextEncoder().encode(JSON.stringify(parseAgentContext(context), null, 2)); +} + +export function isMtmFormatError(error: unknown): error is MtmFormatError { + return error instanceof MtmFormatError; +} diff --git a/src/notebook/commands/compressConversation.ts b/src/notebook/commands/compressConversation.ts index 53d37bb..b21d8b4 100644 --- a/src/notebook/commands/compressConversation.ts +++ b/src/notebook/commands/compressConversation.ts @@ -13,6 +13,7 @@ import { MutsumiSerializer } from '../serializer'; import { formatMessagesToString, createDebugSessionFromNotebook } from './utils'; import { getCompressModelSelection, resolveModelSelection } from '../../utils'; import { t } from '../../i18n'; +import { assistantText } from '../../llm/messageText'; /** * Register the compress conversation command. @@ -98,10 +99,8 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon const conversationText = formatMessagesToString(messages, { includeHeader: false, maxContentLength: 3000 }); // Create compression prompt messages - const compressionMessages: AgentMessage[] = [ - { - role: 'system', - content: 'You are a conversation compression assistant. Your task is to compress a long conversation into a concise summary while preserving all important information, decisions, and context.\n\n' + + const compressionContext = { + systemPrompt: 'You are a conversation compression assistant. Your task is to compress a long conversation into a concise summary while preserving all important information, decisions, and context.\n\n' + 'Requirements:\n' + '1. Summarize the main topics and goals discussed\n' + '2. Preserve all key decisions and conclusions\n' + @@ -109,13 +108,13 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon '4. Maintain the chronological flow of the conversation\n' + '5. Keep the summary concise but comprehensive\n' + '6. Use markdown formatting for clarity\n' + - '7. Do not include meta-commentary about the compression process' - }, - { + '7. Do not include meta-commentary about the compression process', + messages: [{ role: 'user', - content: `Please compress the following conversation into a concise summary:\n\n${conversationText}` - } - ]; + content: `Please compress the following conversation into a concise summary:\n\n${conversationText}`, + timestamp: Date.now(), + } satisfies AgentMessage], + }; // Create lite adapter and session for compression const adapter = new LiteAdapter(); @@ -142,17 +141,17 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon // Run compression const abortController = new AbortController(); - const compressedMessages = await runner.run(abortController, compressionMessages); + const runResult = await runner.run(abortController, compressionContext); + if (runResult.status !== 'completed') { + throw new Error(runResult.error?.message ?? 'Compression was cancelled'); + } // Extract compressed content - const lastAssistantMsg = [...compressedMessages].reverse().find(m => m.role === 'assistant'); - if (!lastAssistantMsg?.content) { + const lastAssistantMsg = [...runResult.messages].reverse().find(m => m.role === 'assistant'); + if (!lastAssistantMsg) { throw new Error('Compression failed: no response from LLM'); } - - const compressedContent = typeof lastAssistantMsg.content === 'string' - ? lastAssistantMsg.content - : JSON.stringify(lastAssistantMsg.content); + const compressedContent = assistantText(lastAssistantMsg); // Generate new file name const originalUri = editor.notebook.uri; @@ -181,7 +180,8 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon // Create single user message with compressed content const compressedContext: AgentMessage[] = [{ role: 'user', - content: `## Conversation Summary\n\n${compressedContent}\n\n---\n\n*This is a compressed version of the original conversation. Original file: ${originalName}*` + content: `## Conversation Summary\n\n${compressedContent}\n\n---\n\n*This is a compressed version of the original conversation. Original file: ${originalName}*`, + timestamp: Date.now(), }]; // Create notebook data using serializer @@ -193,6 +193,7 @@ export function registerCompressConversationCommand(context: vscode.ExtensionCon 'markdown' ) ]); + notebookData.cells[0].metadata = { role: 'user', timestamp: compressedContext[0].timestamp }; notebookData.metadata = compressedMetadata; // Serialize and save diff --git a/src/notebook/commands/selectModel.ts b/src/notebook/commands/selectModel.ts index b6f8f9c..fb58837 100644 --- a/src/notebook/commands/selectModel.ts +++ b/src/notebook/commands/selectModel.ts @@ -84,7 +84,6 @@ export function registerSelectModelCommand(context: vscode.ExtensionContext): vo ) ?? 'default'; const modelItems: SelectModelQuickPickItem[] = []; - let legacyMatched = false; for (const [providerName, providerModels] of providerEntries) { if (providerModels.length === 0) { continue; @@ -96,18 +95,7 @@ export function registerSelectModelCommand(context: vscode.ExtensionContext): vo }); for (const modelInfo of providerModels) { const modelName = modelInfo.id; - // When provider is stored in metadata, match on both model and provider. - // For legacy notebooks without a provider field, fall back to - // first-occurrence match on model name only. - let isCurrent: boolean; - if (currentProvider) { - isCurrent = modelName === currentModel && providerName === currentProvider; - } else { - isCurrent = !legacyMatched && modelName === currentModel; - if (isCurrent) { - legacyMatched = true; - } - } + const isCurrent = modelName === currentModel && providerName === currentProvider; const detail = isCurrent ? '$(check) ' + t('selectModel.current') : undefined; modelItems.push({ itemType: 'model', diff --git a/src/notebook/commands/utils.ts b/src/notebook/commands/utils.ts index 8c48d4b..b3d3f8f 100644 --- a/src/notebook/commands/utils.ts +++ b/src/notebook/commands/utils.ts @@ -5,10 +5,12 @@ import * as vscode from 'vscode'; import { IAgentSession } from '../../adapters/interfaces'; -import { AgentMessage, AgentMetadata } from '../../types'; +import { AgentMessage, AgentMetadata, PersistedAgentMessage } from '../../types'; import { LiteAdapter, LiteAgentSessionConfig } from '../../adapters/liteAdapter'; import { GhostBlock, GhostFileEntry } from '../../contextManagement/interfaces'; import { decodeGhostBlock, removeGhostFiles } from '../../contextManagement/ghostBlocks'; +import { messageText } from '../../llm/messageText'; +import { parsePersistedInteraction } from '../../mtmFormat'; /** * Builds NotebookEdits that strip ghost file entries from every cell's last_ghost_block. @@ -28,6 +30,7 @@ export function buildGhostStripEdits( const edits: vscode.NotebookEdit[] = []; for (let i = 0; i < notebook.cellCount; i++) { const cell = notebook.cellAt(i); + if (cell.kind !== vscode.NotebookCellKind.Code) continue; const raw = cell.metadata?.last_ghost_block; if (raw === undefined || raw === null) { continue; @@ -74,25 +77,8 @@ export function formatMessagesToString( const msg = messages[i]; content += `--- Message ${i + 1} [${msg.role.toUpperCase()}] ---\n\n`; - if (typeof msg.content === 'string') { - const displayContent = maxContentLength < msg.content.length - ? msg.content.substring(0, maxContentLength) + '\n...(truncated)' - : msg.content; - content += displayContent; - } else if (Array.isArray(msg.content)) { - // Handle multi-modal content (text + images) - for (const part of msg.content) { - if (part.type === 'text') { - const displayText = maxContentLength < part.text.length - ? part.text.substring(0, maxContentLength) + '\n...(truncated)' - : part.text; - content += displayText; - } else if (part.type === 'image_url') { - content += '[Image: ' + (part.image_url?.url?.substring(0, 50) || 'unknown') + '...]'; - } - content += '\n'; - } - } + const text = messageText(msg); + content += maxContentLength < text.length ? text.substring(0, maxContentLength) + '\n...(truncated)' : text; content += '\n\n'; } @@ -113,31 +99,24 @@ export async function createDebugSessionFromNotebook( const cell = notebook.cellAt(cellIndex); // Build raw history from cells before current - const history: AgentMessage[] = []; + const history: PersistedAgentMessage[] = []; for (let i = 0; i < cellIndex; i++) { const c = notebook.cellAt(i); - const role = c.metadata?.role || 'user'; + if (c.kind !== vscode.NotebookCellKind.Code) continue; const content = c.document.getText(); - if (content.trim()) { - if (role === 'user') { - history.push({ role: 'user', content }); - // Expand mutsumi_interaction from user cell (contains assistant/tool messages) - const interaction = c.metadata?.mutsumi_interaction as AgentMessage[] | undefined; - if (interaction && Array.isArray(interaction)) { - history.push(...interaction); - } - } else if (role === 'assistant') { - // Assistant cell content is directly in the cell value - history.push({ role: 'assistant', content }); - } - } + history.push({ role: 'user', content, timestamp: c.metadata?.timestamp }); + const interaction = parsePersistedInteraction(c.metadata?.mutsumi_interaction); + if (interaction) history.push(...interaction); } // Collect ghost blocks from previous cells const ghostBlocks: (GhostBlock | null)[] = []; for (let i = 0; i < cellIndex; i++) { - ghostBlocks.push(decodeGhostBlock(notebook.cellAt(i).metadata?.last_ghost_block)); + const previousCell = notebook.cellAt(i); + if (previousCell.kind === vscode.NotebookCellKind.Code) { + ghostBlocks.push(decodeGhostBlock(previousCell.metadata?.last_ghost_block)); + } } const adapter = new LiteAdapter(); diff --git a/src/notebook/serializer.ts b/src/notebook/serializer.ts index b030056..8242d81 100644 --- a/src/notebook/serializer.ts +++ b/src/notebook/serializer.ts @@ -1,6 +1,13 @@ import * as vscode from 'vscode'; import { TextDecoder, TextEncoder } from 'util'; -import { AgentContext, AgentMessage, AgentMetadata, MessageContent } from '../types'; +import { + AgentContext, + AgentMessage, + AgentMetadata, + MTM_FORMAT_VERSION, + NotebookNote, + PersistedAgentMessage, +} from '../types'; import { AgentOrchestrator } from '../agent/agentOrchestrator'; import { ToolManager } from '../tools.d/toolManager'; import { v4 as uuidv4 } from 'uuid'; @@ -11,6 +18,13 @@ import { GhostBlock } from '../contextManagement/interfaces'; import { decodeGhostBlock } from '../contextManagement/ghostBlocks'; import { t } from '../i18n'; import type { McpToolSelection } from '../mcp/interfaces'; +import { + decodeAgentContext, + encodeAgentContext, + isMtmFormatError, + parsePersistedInteraction, + UNSUPPORTED_MTM_FORMAT, +} from '../mtmFormat'; // ============================================================================ // Core Data Structures (VSCode-agnostic) @@ -21,48 +35,53 @@ import type { McpToolSelection } from '../mcp/interfaces'; * Used by both NotebookSerializer and HeadlessAdapter. */ export interface GenericCellData { - /** Cell kind: 1 = Markup (assistant), 2 = Code (user) */ + /** Cell kind: 1 = Markup note, 2 = Code user turn */ kind: 1 | 2; /** Cell content value */ value: string; /** Cell metadata including role, ghost blocks, interaction */ metadata?: { - role?: 'user' | 'assistant' | 'system'; + role?: 'user' | 'note'; + timestamp?: unknown; /** Raw persisted ghost block metadata; decoded at adapter/serializer boundaries */ last_ghost_block?: unknown; - mutsumi_interaction?: AgentMessage[]; + mutsumi_interaction?: PersistedAgentMessage[]; [key: string]: any; }; } /** - * Result of converting AgentMessage array to cells. + * Result of converting persisted messages to cells. */ export interface MessageToCellsResult { cells: GenericCellData[]; } /** - * Convert AgentMessage array to generic cells (message grouping logic). + * Convert persisted messages and notes to generic cells (message grouping logic). * This is the core algorithm shared between Notebook and Headless adapters. * * Rules: * - User messages become Code cells (kind: 2) - * - Assistant messages become Markup cells (kind: 1) - * - Consecutive assistant + tool messages are grouped into one cell's mutsumi_interaction - * - System messages become Markup cells with special formatting + * - Markup cells are user-only notes restored from the top-level notes array + * - Consecutive assistant + toolResult messages are grouped into one cell's mutsumi_interaction * - * IMPORTANT: mutsumi_interaction ONLY exists on user cells, never on assistant cells. + * IMPORTANT: mutsumi_interaction ONLY exists on user cells, never on note cells. * Assistant/tool messages following a user message are stored in that user cell's * mutsumi_interaction array for rendering as output. */ -export function messagesToGenericCells(messages: AgentMessage[]): GenericCellData[] { +export function messagesToGenericCells( + messages: PersistedAgentMessage[], + notes: NotebookNote[] = [], +): GenericCellData[] { debugLogger.log(`[messagesToGenericCells] ==== START, input message count: ${messages?.length ?? 0} ====`); const cells: GenericCellData[] = []; if (!messages || messages.length === 0) { - debugLogger.log('[messagesToGenericCells] Empty messages array, returning empty cells'); - return cells; + debugLogger.log('[messagesToGenericCells] Empty messages array, returning note cells only'); + return notes + .filter(note => note.beforeUserIndex === 0) + .map(note => ({ kind: 1, value: note.markdown, metadata: { role: 'note' } })); } for (let i = 0; i < messages.length; i++) { @@ -76,23 +95,21 @@ export function messagesToGenericCells(messages: AgentMessage[]): GenericCellDat const cell: GenericCellData = { kind: 2, value: cellValue, - metadata: { role: 'user' } + metadata: { role: 'user', timestamp: msg.timestamp } }; // Preserve metadata (especially ghost block state) - if (msg.metadata) { - const { mutsumi_interaction, role, ...rest } = msg.metadata; - cell.metadata = { ...cell.metadata, ...rest }; - debugLogger.log(`[messagesToGenericCells] - Preserved metadata keys: ${Object.keys(rest).join(',')}`); + if (msg.mutsumi?.ghostBlock) { + cell.metadata!.last_ghost_block = msg.mutsumi.ghostBlock; } // Look ahead for associated assistant/tool messages // These will be stored in mutsumi_interaction and rendered as this cell's output - const group: AgentMessage[] = []; + const group: PersistedAgentMessage[] = []; let j = i + 1; while (j < messages.length) { const next = messages[j]; - if (next.role === 'user' || next.role === 'system') { + if (next.role === 'user') { break; } group.push(next); @@ -108,62 +125,34 @@ export function messagesToGenericCells(messages: AgentMessage[]): GenericCellDat cells.push(cell); debugLogger.log(`[messagesToGenericCells] - Added user cell #${cells.length}`); - } else if (msg.role === 'system') { - // System message as Markup cell - const cellValue = serializeContentToString(msg.content); - debugLogger.log(`[messagesToGenericCells] - System cell, content length: ${cellValue.length}`); - cells.push({ - kind: 1, - value: `**System**: ${cellValue}`, - metadata: { role: 'system' } - }); - debugLogger.log(`[messagesToGenericCells] - Added system cell #${cells.length}`); } else { - // Assistant/tool message WITHOUT a preceding user message - // This is an orphan message (e.g., file starts with assistant message) - // Create a standalone assistant cell with NO mutsumi_interaction - debugLogger.log(`[messagesToGenericCells] - Orphan assistant/tool message (no preceding user), starting group...`); - const group: AgentMessage[] = [msg]; - - while (i + 1 < messages.length) { - const next = messages[i + 1]; - if (next.role === 'user' || next.role === 'system') { - break; - } - group.push(next); - i++; - } + throw new Error(t('serializer.standaloneMessagesUnsupported', MTM_FORMAT_VERSION)); + } + } - debugLogger.log(`[messagesToGenericCells] - Orphan group formed with ${group.length} messages`); - // Orphan cells have no output area; render blocks are flattened to markdown cell source - const displayText = renderBlocksToMarkdown(buildInteractionRenderBlocks(group, false)); - - cells.push({ - kind: 1, - value: displayText, - metadata: { - role: 'assistant' - // NOTE: No mutsumi_interaction here! Orphan assistant messages - // are rendered directly to cell value, not stored in metadata. - } - }); - debugLogger.log(`[messagesToGenericCells] - Added orphan assistant cell #${cells.length}, displayText length: ${displayText.length}`); + const interleaved: GenericCellData[] = []; + for (let beforeUserIndex = 0; beforeUserIndex <= cells.length; beforeUserIndex++) { + for (const note of notes) { + if (note.beforeUserIndex === beforeUserIndex) { + interleaved.push({ kind: 1, value: note.markdown, metadata: { role: 'note' } }); + } } + if (beforeUserIndex < cells.length) interleaved.push(cells[beforeUserIndex]); } - debugLogger.log(`[messagesToGenericCells] ==== END, generated ${cells.length} cells ====`); - return cells; + debugLogger.log(`[messagesToGenericCells] ==== END, generated ${interleaved.length} cells ====`); + return interleaved; } /** - * Convert generic cells back to AgentMessage array. + * Convert generic cells back to persisted messages. * Used for serialization to file. * - * NOTE: mutsumi_interaction is ONLY expanded from user cells, never from assistant cells. + * NOTE: mutsumi_interaction is ONLY expanded from user cells; Markup notes are skipped. */ -export function genericCellsToMessages(cells: GenericCellData[]): AgentMessage[] { +export function genericCellsToMessages(cells: GenericCellData[]): PersistedAgentMessage[] { debugLogger.log(`[genericCellsToMessages] ==== START, input ${cells?.length ?? 0} cells ====`); - const messages: AgentMessage[] = []; + const messages: PersistedAgentMessage[] = []; if (!cells || cells.length === 0) { debugLogger.log('[genericCellsToMessages] Empty cells array, returning empty messages'); @@ -172,31 +161,26 @@ export function genericCellsToMessages(cells: GenericCellData[]): AgentMessage[] for (let idx = 0; idx < cells.length; idx++) { const cell = cells[idx]; - const role = cell.metadata?.role || 'user'; + if (cell.kind === 1) { + debugLogger.log(`[genericCellsToMessages] Cell ${idx}: skipped Markup note`); + continue; + } + const role = 'user'; debugLogger.log(`[genericCellsToMessages] Cell ${idx}: kind=${cell.kind}, role=${role}, value length=${cell.value?.length ?? 0}`); - if (role === 'system') { - messages.push({ - role: 'system', - content: cell.value.replace('**System**: ', '') - }); - debugLogger.log(`[genericCellsToMessages] - Added system message`); - } else if (role === 'user') { + if (role === 'user') { // Strip ghost block from persisted content const cleanContent = stripGhostBlockFromCell(cell.value); - const userMsg: AgentMessage = { + const userMsg: PersistedAgentMessage = { role: 'user', - content: cleanContent + content: parseSerializedUserContent(cleanContent), + timestamp: cell.metadata?.timestamp, }; - // Preserve metadata (especially ghost block state) - if (cell.metadata) { - const { mutsumi_interaction, role, ...rest } = cell.metadata; - if (Object.keys(rest).length > 0) { - userMsg.metadata = rest; - debugLogger.log(`[genericCellsToMessages] - Preserved metadata keys: ${Object.keys(rest).join(',')}`); - } + const ghostBlock = decodeGhostBlock(cell.metadata?.last_ghost_block); + if (ghostBlock) { + userMsg.mutsumi = { ghostBlock }; } messages.push(userMsg); @@ -204,14 +188,14 @@ export function genericCellsToMessages(cells: GenericCellData[]): AgentMessage[] // Expand interaction if exists (ONLY for user cells) if (cell.metadata?.mutsumi_interaction) { - messages.push(...cell.metadata.mutsumi_interaction); - debugLogger.log(`[genericCellsToMessages] - Expanded interaction: ${cell.metadata.mutsumi_interaction.length} messages`); + const interaction = parsePersistedInteraction(cell.metadata.mutsumi_interaction); + if (interaction) { + messages.push(...interaction); + debugLogger.log(`[genericCellsToMessages] - Expanded interaction: ${interaction.length} messages`); + } else { + debugLogger.log(`[genericCellsToMessages] - Ignored malformed interaction on cell ${idx}`); + } } - } else { - // Assistant cell: use cell value directly, ignore any mutsumi_interaction - // (mutsumi_interaction should never exist on assistant cells, but handle gracefully) - messages.push({ role: 'assistant', content: cell.value }); - debugLogger.log(`[genericCellsToMessages] - Added assistant message from cell value, content length: ${cell.value.length}`); } } @@ -219,6 +203,17 @@ export function genericCellsToMessages(cells: GenericCellData[]): AgentMessage[] return messages; } +/** Extract Markup notes, anchored by the number of preceding Code/user cells. */ +export function extractNotebookNotes(cells: GenericCellData[]): NotebookNote[] { + const notes: NotebookNote[] = []; + let userCount = 0; + for (const cell of cells) { + if (cell.kind === 2) userCount++; + else notes.push({ beforeUserIndex: userCount, markdown: cell.value }); + } + return notes; +} + /** * Extract and decode ghost blocks from generic cells. * Returns one entry per user cell in order; absent or structurally invalid @@ -240,85 +235,42 @@ export function extractGhostBlocksFromCells(cells: GenericCellData[]): (GhostBlo /** * Build RenderBlocks from an interaction message group. - * Pure function shared by deserializeNotebook output generation and orphan cell rendering. + * Pure function shared by deserializeNotebook output generation. */ -function buildInteractionRenderBlocks(group: AgentMessage[], isSubAgent: boolean): RenderBlock[] { +function buildInteractionRenderBlocks(group: PersistedAgentMessage[], isSubAgent: boolean): RenderBlock[] { const blocks: RenderBlock[] = []; - const toolCallMap = new Map(); + const toolResults = new Map>(); + for (const message of group) { + if (message.role === 'toolResult') toolResults.set(message.toolCallId, message); + } for (const m of group) { if (m.role === 'assistant') { - // Build tool call map - if (m.tool_calls) { - for (const tc of m.tool_calls) { - let parsedArgs: any = {}; - if (tc.function?.arguments) { - try { parsedArgs = JSON.parse(tc.function.arguments); } catch { parsedArgs = {}; } - } - if (tc.id) { - toolCallMap.set(tc.id, { name: tc.function.name, args: parsedArgs }); - } + for (const part of m.content) { + if (part.type === 'thinking' && part.thinking) { + blocks.push({ type: 'reasoning', markdown: part.thinking, collapsed: true }); + } else if (part.type === 'text' && part.text) { + blocks.push({ type: 'content', markdown: part.text }); + } else if (part.type === 'toolCall') { + const result = toolResults.get(part.id); + const summary = ToolManager.getInstance().getPrettyPrint(part.name, part.arguments, isSubAgent); + const renderingConfig = ToolManager.getInstance().getToolRenderingConfig(part.name, isSubAgent); + blocks.push({ + type: 'toolCall', + name: part.name, + args: part.arguments, + summary, + result: result ? serializeContentToString(result.content) : undefined, + isStreaming: false, + renderingConfig, + }); } } - // Add reasoning block if exists - const reasoningStr = m.reasoning_content || ''; - if (reasoningStr) { - blocks.push({ type: 'reasoning', markdown: reasoningStr, collapsed: true }); - } - // Add content block if exists - const contentStr = serializeContentToString(m.content); - if (contentStr) { - blocks.push({ type: 'content', markdown: contentStr }); - } - } else if (m.role === 'tool') { - // Add tool call block - const contentStr = serializeContentToString(m.content); - const mapped = m.tool_call_id ? toolCallMap.get(m.tool_call_id) : undefined; - const toolName = mapped?.name ?? m.name ?? 'unknown'; - const args = mapped?.args ?? {}; - const prettyPrintSummary = mapped - ? ToolManager.getInstance().getPrettyPrint(toolName, args, isSubAgent) - : `Tool Call: ${toolName}`; - - // Look up code-block rendering hints so args like new_content are - // rendered as
 blocks (with language detection) instead
-            // of plain list items when the notebook is re-opened from disk.
-            const renderingConfig = ToolManager.getInstance().getToolRenderingConfig(toolName, isSubAgent);
-
-            blocks.push({
-                type: 'toolCall',
-                name: toolName,
-                args: args,
-                summary: prettyPrintSummary,
-                result: contentStr,
-                isStreaming: false,
-                renderingConfig
-            });
         }
     }
     return blocks;
 }
 
-/**
- * Flatten RenderBlocks to a plain markdown string.
- * Used for orphan assistant cells whose content is stored directly in cell source
- * (these cells have no output area, so the custom renderer cannot be used).
- */
-function renderBlocksToMarkdown(blocks: RenderBlock[]): string {
-    const parts: string[] = [];
-    for (const block of blocks) {
-        if (block.type === 'reasoning') {
-            parts.push(`> **Reasoning**\n>\n> ${block.markdown.split('\n').join('\n> ')}`);
-        } else if (block.type === 'content') {
-            parts.push(block.markdown);
-        } else if (block.type === 'toolCall') {
-            const header = block.summary || `Tool Call: ${block.name}`;
-            parts.push(`**${header}**${block.result ? `\n\n\`\`\`\n${block.result}\n\`\`\`` : ''}`);
-        }
-    }
-    return parts.join('\n\n');
-}
-
 /**
  * Strip ghost block from cell content.
  */
@@ -331,18 +283,35 @@ function stripGhostBlockFromCell(value: string): string {
     return value;
 }
 
+/** Restore native image blocks emitted by serializeContentToString. */
+function parseSerializedUserContent(value: string): Extract['content'] {
+    const pattern = /!\[[^\]]*\]\(data:([^;,]+);base64,([^)]+)\)/g;
+    const matches = [...value.matchAll(pattern)];
+    if (matches.length === 0) return value;
+    const parts: Extract['content'] = [];
+    let offset = 0;
+    for (const match of matches) {
+        const index = match.index ?? 0;
+        if (index > offset) parts.push({ type: 'text', text: value.slice(offset, index) });
+        parts.push({ type: 'image', mimeType: match[1], data: match[2] });
+        offset = index + match[0].length;
+    }
+    if (offset < value.length) parts.push({ type: 'text', text: value.slice(offset) });
+    return parts;
+}
+
 /**
  * Serialize message content to string.
  */
-function serializeContentToString(content: MessageContent | null | undefined): string {
+function serializeContentToString(content: string | readonly ({ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string })[]): string {
     if (!content) return '';
     if (typeof content === 'string') return content;
 
     return content.map(part => {
         if (part.type === 'text') {
             return part.text;
-        } else if (part.type === 'image_url') {
-            return `![image](${part.image_url.url})`;
+        } else if (part.type === 'image') {
+            return `![image](data:${part.mimeType};base64,${part.data})`;
         }
         return '';
     }).join('');
@@ -378,39 +347,23 @@ export class MutsumiSerializer implements vscode.NotebookSerializer {
         _token: vscode.CancellationToken
     ): Promise {
         debugLogger.log('[deserializeNotebook] ==== START ====');
-        const contents = new TextDecoder().decode(content);
-        debugLogger.log(`[deserializeNotebook] Decoded content length: ${contents.length} chars`);
-
         let raw: AgentContext;
         try {
-            raw = JSON.parse(contents);
-            debugLogger.log(`[deserializeNotebook] JSON parsed successfully`);
-            debugLogger.log(`[deserializeNotebook] Metadata uuid: ${raw.metadata?.uuid}`);
-            debugLogger.log(`[deserializeNotebook] Context message count: ${raw.context?.length ?? 0}`);
-            if (raw.context && raw.context.length > 0) {
-                raw.context.forEach((msg, idx) => {
-                    debugLogger.log(`[deserializeNotebook] Message ${idx}: role=${msg.role}, content length=${typeof msg.content === 'string' ? msg.content.length : JSON.stringify(msg.content).length}`);
-                });
+            raw = decodeAgentContext(content);
+        } catch (error) {
+            if (isMtmFormatError(error)) {
+                const message = error.code === UNSUPPORTED_MTM_FORMAT
+                    ? t('serializer.unsupportedFormat', MTM_FORMAT_VERSION, String(error.actualVersion))
+                    : t('serializer.invalidFormat', error.message);
+                void vscode.window.showErrorMessage(message);
             }
-        } catch (err) {
-            debugLogger.log(`[deserializeNotebook] JSON parse FAILED: ${err}`);
-            // Create default Agent context when parsing fails
-            raw = {
-                metadata: {
-                    uuid: uuidv4(),
-                    name: t('serializer.newAgent'),
-                    created_at: new Date().toISOString(),
-                    parent_agent_id: null,
-                    allowed_uris: ['/'],
-                    contextItems: []
-                },
-                context: []
-            };
+            throw error;
         }
+        debugLogger.log(`[deserializeNotebook] Parsed formatVersion=${raw.formatVersion}, uuid=${raw.metadata.uuid}`);
 
         // Use generic cell conversion
         debugLogger.log(`[deserializeNotebook] Converting ${raw.context?.length ?? 0} messages to generic cells...`);
-        const genericCells = messagesToGenericCells(raw.context);
+        const genericCells = messagesToGenericCells(raw.context, raw.notes);
         debugLogger.log(`[deserializeNotebook] Generated ${genericCells.length} generic cells`);
         genericCells.forEach((cell, idx) => {
             debugLogger.log(`[deserializeNotebook] GenericCell ${idx}: kind=${cell.kind}, role=${cell.metadata?.role}, value length=${cell.value?.length ?? 0}, has interaction=${!!cell.metadata?.mutsumi_interaction}`);
@@ -489,6 +442,7 @@ export class MutsumiSerializer implements vscode.NotebookSerializer {
         });
 
         const raw: AgentContext = {
+            formatVersion: MTM_FORMAT_VERSION,
             metadata: {
                 uuid: uuid ?? uuidv4(),
                 name: t('serializer.newAgent'),
@@ -511,7 +465,7 @@ export class MutsumiSerializer implements vscode.NotebookSerializer {
             },
             context: []
         };
-        return new TextEncoder().encode(JSON.stringify(raw, null, 2));
+        return encodeAgentContext(raw);
     }
 
     /**
@@ -545,6 +499,7 @@ export class MutsumiSerializer implements vscode.NotebookSerializer {
         // Use generic conversion
         debugLogger.log(`[serializeNotebook] Converting ${genericCells.length} generic cells to messages...`);
         const context = genericCellsToMessages(genericCells);
+        const notes = extractNotebookNotes(genericCells);
         debugLogger.log(`[serializeNotebook] Generated ${context.length} messages`);
         context.forEach((msg, idx) => {
             debugLogger.log(`[serializeNotebook] Message ${idx}: role=${msg.role}, content length=${typeof msg.content === 'string' ? msg.content.length : JSON.stringify(msg.content).length}`);
@@ -563,11 +518,13 @@ export class MutsumiSerializer implements vscode.NotebookSerializer {
         }
 
         const output: AgentContext = {
+            formatVersion: MTM_FORMAT_VERSION,
             metadata,
-            context
+            context,
+            ...(notes.length > 0 ? { notes } : {}),
         };
 
-        const encoded = new TextEncoder().encode(JSON.stringify(output, null, 2));
+        const encoded = encodeAgentContext(output);
         debugLogger.log(`[serializeNotebook] ==== END, output size: ${encoded.length} bytes ====`);
         return encoded;
     }
diff --git a/src/types.ts b/src/types.ts
index 372ec63..8c7efe7 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -3,6 +3,15 @@
  * @module types
  */
 
+import type {
+    AssistantMessage,
+    ImageContent,
+    TextContent,
+    ToolResultMessage,
+    UserMessage,
+} from '@earendil-works/pi-ai';
+import type { GhostBlock } from './contextManagement/interfaces';
+
 /**
  * Explicit model + provider pair. Used throughout settings, configuration,
  * persistence, and execution to avoid ambiguous first-match resolution.
@@ -15,9 +24,6 @@ export interface ModelSelection {
     provider: string;
 }
 
-/**
- * Default providers used when user hasn't configured any providers.
- */
 /**
  * Built-in default model selection pair.
  */
@@ -73,55 +79,128 @@ export interface AgentMetadata {
  * Text content part for multimodal messages.
  * @interface ContentPartText
  */
-export type ContentPartText = { type: 'text'; text: string };
+export type ContentPartText = TextContent;
 
 /**
  * Image content part for multimodal messages.
  * @interface ContentPartImage
  */
-export type ContentPartImage = { 
-    type: 'image_url'; 
-    image_url: { 
-        url: string; 
-        detail?: 'auto' | 'low' | 'high' 
-    } 
-};
+export type ContentPartImage = ImageContent;
 
 /**
  * Message content can be plain text or multimodal parts.
  */
-export type MessageContent = string | (ContentPartText | ContentPartImage)[];
+export type MessageContent = UserMessage['content'];
+
+/** Mutsumi-only state attached to persisted user messages. */
+export interface MutsumiUserMessageState {
+    ghostBlock?: GhostBlock;
+}
 
 /**
  * Message in an agent conversation.
  * @interface AgentMessage
  */
-export interface AgentMessage {
-    /** Role of the message sender */
-    role: 'user' | 'assistant' | 'system' | 'tool';
-    /** Message content, null if only tool calls */
-    content: MessageContent | null;
-    /** Tool calls requested by assistant */
-    tool_calls?: any[];
-    /** ID of the tool call this message responds to */
-    tool_call_id?: string;
-    /** Name of the tool being called */
-    name?: string;
-    /** Reasoning/thinking content from the model */
-    reasoning_content?: string;
-    /** Additional durable metadata, including versioned pi-ai replay state and ghost blocks. */
-    metadata?: import('./llm/types').LlmMessageMetadata & Record;
+export type AgentMessage =
+    | (UserMessage & { mutsumi?: MutsumiUserMessageState })
+    | AssistantMessage
+    | ToolResultMessage;
+
+export type PersistedTextContent = {
+    type: 'text';
+    text: string;
+    textSignature?: unknown;
+};
+
+export type PersistedImageContent = {
+    type: 'image';
+    data: string;
+    mimeType: string;
+};
+
+export type PersistedThinkingContent = {
+    type: 'thinking';
+    thinking: string;
+    thinkingSignature?: unknown;
+    redacted?: unknown;
+};
+
+export type PersistedToolCall = {
+    type: 'toolCall';
+    id: string;
+    name: string;
+    arguments: Record;
+    thoughtSignature?: unknown;
+};
+
+/**
+ * On-disk messages keep the pi-ai semantic core strict while allowing provider
+ * envelope metadata to evolve independently of the .mtm format.
+ */
+export type PersistedUserMessage = {
+    role: 'user';
+    content: string | (PersistedTextContent | PersistedImageContent)[];
+    timestamp?: unknown;
+    mutsumi?: MutsumiUserMessageState;
+};
+
+export type PersistedAssistantMessage = {
+    role: 'assistant';
+    content: (PersistedTextContent | PersistedThinkingContent | PersistedToolCall)[];
+    api: string;
+    provider: string;
+    model: string;
+    usage?: unknown;
+    cost?: unknown;
+    timestamp?: unknown;
+    stopReason?: unknown;
+    responseId?: unknown;
+    responseModel?: unknown;
+    errorMessage?: unknown;
+    diagnostics?: unknown;
+};
+
+export type PersistedToolResultMessage = {
+    role: 'toolResult';
+    toolCallId: string;
+    toolName: string;
+    content: (PersistedTextContent | PersistedImageContent)[];
+    isError: boolean;
+    timestamp?: unknown;
+    usage?: unknown;
+    details?: unknown;
+    addedToolNames?: unknown;
+};
+
+export type PersistedAgentMessage =
+    | PersistedUserMessage
+    | PersistedAssistantMessage
+    | PersistedToolResultMessage;
+
+/** A user-authored Markup cell that is persisted but never sent to a model. */
+export interface NotebookNote {
+    /** Number of user cells that precede this note. */
+    beforeUserIndex: number;
+    /** Original Markdown source. */
+    markdown: string;
 }
 
+/** Current, deliberately strict on-disk .mtm format version. */
+export const MTM_FORMAT_VERSION = 1 as const;
+
 /**
  * Complete agent context including metadata and conversation history.
  * @interface AgentContext
  */
 export interface AgentContext {
+    /** Required on-disk format discriminator. Unversioned files are unsupported. */
+    formatVersion: typeof MTM_FORMAT_VERSION;
     /** Agent metadata */
     metadata: AgentMetadata;
     /** Conversation message history */
-    context: AgentMessage[];
+    context: PersistedAgentMessage[];
+    /** User-authored Markup cells, anchored between user cells. */
+    notes?: NotebookNote[];
 }
 
 /**
diff --git a/tests/agentRunnerStatus.test.ts b/tests/agentRunnerStatus.test.ts
new file mode 100644
index 0000000..2952c00
--- /dev/null
+++ b/tests/agentRunnerStatus.test.ts
@@ -0,0 +1,201 @@
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+import type { AssistantMessage, ToolCall } from '@earendil-works/pi-ai';
+
+const state = vi.hoisted(() => ({
+    steps: [] as Array<{ message?: AssistantMessage; error?: Error & { code?: string } }>,
+    cancelDuringTools: false,
+    sessionCancelled: false,
+    toolError: undefined as (Error & { code?: string }) | undefined,
+}));
+
+vi.mock('vscode', () => ({
+    window: { showErrorMessage: vi.fn(() => Promise.resolve(undefined)) },
+    env: { clipboard: { writeText: vi.fn() } },
+    workspace: { getConfiguration: () => ({ get: () => undefined }) },
+    l10n: { t: (value: string) => value },
+}));
+
+vi.mock('../src/agent/llmClient', () => ({
+    LLMClient: class {},
+}));
+
+vi.mock('../src/agent/llmStream', () => ({
+    LLMStreamHandler: class {
+        async streamResponse() {
+            const step = state.steps.shift();
+            if (!step) throw new Error('Missing test stream step');
+            if (step.error) throw step.error;
+            return { message: step.message };
+        }
+    },
+}));
+
+vi.mock('../src/agent/toolExecutor', () => ({
+    ToolExecutor: class {
+        async executeTools(toolCalls: ToolCall[]) {
+            if (state.toolError) throw state.toolError;
+            if (state.cancelDuringTools) state.sessionCancelled = true;
+            return {
+                messages: toolCalls.map(call => ({
+                    role: 'toolResult' as const,
+                    toolCallId: call.id,
+                    toolName: call.name,
+                    content: [{ type: 'text' as const, text: 'ok' }],
+                    isError: false,
+                    timestamp: 3,
+                })),
+                shouldTerminate: false,
+                isTaskComplete: false,
+            };
+        }
+    },
+}));
+
+vi.mock('../src/agent/titleGenerator', () => ({
+    TitleGenerator: class {},
+}));
+
+vi.mock('../src/adapters/liteAdapter', () => ({
+    LiteAgentSession: class {},
+}));
+
+import { AgentRunner } from '../src/agent/agentRunner';
+
+function assistant(content: AssistantMessage['content'], stopReason: AssistantMessage['stopReason'] = 'stop'): AssistantMessage {
+    return {
+        role: 'assistant',
+        api: 'openai-completions',
+        provider: 'test-provider',
+        model: 'test-model',
+        content,
+        stopReason,
+        timestamp: 2,
+        usage: {
+            input: 1, output: 1, cacheRead: 0, cacheWrite: 0, totalTokens: 2,
+            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
+        },
+    };
+}
+
+function createRunner(maxLoops = 2) {
+    const session = {
+        id: 'session',
+        token: { get isCancellationRequested() { return state.sessionCancelled; } },
+        getConfig: vi.fn(async () => ({ allowedUris: [], isSubAgent: false })),
+        replaceOutput: vi.fn(async () => undefined),
+    };
+    const toolSet = {
+        getDefinitions: () => [],
+    };
+    return new AgentRunner(
+        { provider: 'test-provider', model: 'test-model', maxLoops },
+        toolSet as any,
+        session as any,
+    );
+}
+
+describe('AgentRunner run status', () => {
+    beforeEach(() => {
+        state.steps = [];
+        state.cancelDuringTools = false;
+        state.sessionCancelled = false;
+        state.toolError = undefined;
+        vi.spyOn(console, 'error').mockImplementation(() => undefined);
+    });
+
+    afterEach(() => vi.restoreAllMocks());
+
+    it('returns completed with the exact native assistant message', async () => {
+        const message = assistant([{ type: 'text', text: 'done', textSignature: 'signed' }]);
+        state.steps.push({ message });
+
+        const result = await createRunner(1).run(new AbortController(), {
+            messages: [{ role: 'user', content: 'go', timestamp: 1 }],
+        });
+
+        expect(result).toEqual({ status: 'completed', messages: [message] });
+    });
+
+    it('reports failure without fabricating an assistant and retains a completed tool round', async () => {
+        const toolRound = assistant([
+            { type: 'toolCall', id: 'call-1', name: 'read', arguments: { path: 'a.ts' } },
+        ], 'toolUse');
+        const failure = Object.assign(new Error('upstream unavailable'), { code: 'UPSTREAM_UNAVAILABLE' });
+        state.steps.push({ message: toolRound }, { error: failure });
+
+        const result = await createRunner().run(new AbortController(), {
+            messages: [{ role: 'user', content: 'go', timestamp: 1 }],
+        });
+
+        expect(result.status).toBe('failed');
+        expect(result.error).toEqual({ code: 'UPSTREAM_UNAVAILABLE', message: 'upstream unavailable' });
+        expect(result.messages).toEqual([
+            toolRound,
+            expect.objectContaining({ role: 'toolResult', toolCallId: 'call-1', isError: false }),
+        ]);
+    });
+
+    it('reports cancellation without persisting a synthetic assistant', async () => {
+        const cancellation = new Error('cancelled');
+        cancellation.name = 'AbortError';
+        state.steps.push({ error: cancellation });
+
+        const result = await createRunner(1).run(new AbortController(), {
+            messages: [{ role: 'user', content: 'go', timestamp: 1 }],
+        });
+
+        expect(result).toEqual({ status: 'cancelled', messages: [] });
+    });
+
+    it('drops an assistant tool round cancelled before it becomes replayable', async () => {
+        state.cancelDuringTools = true;
+        state.steps.push({
+            message: assistant([
+                { type: 'toolCall', id: 'call-1', name: 'write', arguments: { path: 'a.ts' } },
+            ], 'toolUse'),
+        });
+
+        const result = await createRunner().run(new AbortController(), {
+            messages: [{ role: 'user', content: 'go', timestamp: 1 }],
+        });
+
+        expect(result).toEqual({ status: 'cancelled', messages: [] });
+    });
+
+    it('reports tool infrastructure failure without leaving a dangling tool call', async () => {
+        state.toolError = new Error('renderer disconnected');
+        state.steps.push({
+            message: assistant([
+                { type: 'toolCall', id: 'call-1', name: 'read', arguments: { path: 'a.ts' } },
+            ], 'toolUse'),
+        });
+
+        const result = await createRunner().run(new AbortController(), {
+            messages: [{ role: 'user', content: 'go', timestamp: 1 }],
+        });
+
+        expect(result).toEqual({
+            status: 'failed',
+            messages: [],
+            error: { code: 'TOOL_EXECUTION_ERROR', message: 'renderer disconnected' },
+        });
+    });
+
+    it('reports max-loop exhaustion while retaining the completed tool round', async () => {
+        const toolRound = assistant([
+            { type: 'toolCall', id: 'call-1', name: 'read', arguments: { path: 'a.ts' } },
+        ], 'toolUse');
+        state.steps.push({ message: toolRound });
+
+        const result = await createRunner(1).run(new AbortController(), {
+            messages: [{ role: 'user', content: 'go', timestamp: 1 }],
+        });
+
+        expect(result.status).toBe('failed');
+        expect(result.error).toEqual({
+            code: 'MAX_LOOPS_EXCEEDED',
+            message: 'Agent reached the maximum of 1 tool interaction loops',
+        });
+        expect(result.messages).toHaveLength(2);
+    });
+});
diff --git a/tests/llmClient.test.ts b/tests/llmClient.test.ts
index a3a4829..a2de8db 100644
--- a/tests/llmClient.test.ts
+++ b/tests/llmClient.test.ts
@@ -40,14 +40,17 @@ describe.each([
         const client = new LLMClient({ provider: `mock-${api}`, model: 'model', reasoningEffort: 'none' });
         const chunks = [];
         for await (const chunk of client.streamChatCompletion({
-            messages: [{ role: 'system', content: 'rules' }, { role: 'user', content: 'read it' }],
+            systemPrompt: 'rules',
+            messages: [{ role: 'user', content: 'read it', timestamp: 1 }],
             tools: [{ type: 'function', function: { name: 'read', parameters: { type: 'object' } } }],
         })) chunks.push(chunk);
 
-        expect(chunks[0].tool_calls?.[0]).toMatchObject({
-            id: 'call-1', function: { name: 'read', arguments: '{"path":"file.ts"}' },
+        expect(chunks[0]).toMatchObject({
+            type: 'toolcall_end', toolCall: { id: 'call-1', name: 'read', arguments: { path: 'file.ts' } },
+        });
+        expect(chunks.at(-1)).toMatchObject({
+            type: 'done', message: { api, provider: `mock-${api}`, stopReason: 'toolUse' },
         });
-        expect(chunks.at(-1)?.replayState).toMatchObject({ api, provider: `mock-${api}`, stopReason: 'toolUse' });
         expect(state.captured.context).toMatchObject({ systemPrompt: 'rules', tools: [{ name: 'read' }] });
         expect(state.captured.options).toMatchObject({ maxRetries: 0 });
         expect(state.captured.options).toMatchObject({ reasoning: 'off' });
diff --git a/tests/migration.test.ts b/tests/migration.test.ts
deleted file mode 100644
index 4cc055d..0000000
--- a/tests/migration.test.ts
+++ /dev/null
@@ -1,113 +0,0 @@
-import { beforeEach, describe, expect, it, vi } from 'vitest';
-
-type Values = Record;
-const state = vi.hoisted(() => ({
-    global: {} as Values,
-    workspace: {} as Values,
-    folders: new Map(),
-    updates: [] as Array<{ resource?: string; key: string; value: unknown; target: number }>,
-    fail: undefined as undefined | ((resource: string | undefined, key: string, value: unknown, target: number) => boolean),
-    storeApiKey: vi.fn(),
-    reload: vi.fn(),
-    builtInRoutes: new Set(['kimi-coding']),
-}));
-
-vi.mock('vscode', () => {
-    const ConfigurationTarget = { Global: 1, Workspace: 2, WorkspaceFolder: 3 };
-    const getValues = (resource?: { path: string }) => resource ? state.folders.get(resource.path) ?? {} : {};
-    return {
-        ConfigurationTarget,
-        workspace: {
-            workspaceFolders: [{ uri: { path: '/one' } }, { uri: { path: '/two' } }],
-            getConfiguration: (_section: string, resource?: { path: string }) => ({
-                inspect: (key: string) => ({
-                    globalValue: state.global[key],
-                    workspaceValue: state.workspace[key],
-                    workspaceFolderValue: getValues(resource)[key],
-                }),
-                update: async (key: string, value: unknown, target: number) => {
-                    const resourcePath = resource?.path;
-                    state.updates.push({ resource: resourcePath, key, value, target });
-                    if (state.fail?.(resourcePath, key, value, target)) throw new Error('write failed');
-                    const values = target === 1 ? state.global : target === 2 ? state.workspace : getValues(resource);
-                    if (value === undefined) delete values[key]; else values[key] = value;
-                },
-            }),
-        },
-        window: { showWarningMessage: vi.fn(), showInformationMessage: vi.fn(), showErrorMessage: vi.fn() },
-        commands: { registerCommand: vi.fn(() => ({ dispose() {} })) },
-        l10n: { t: (key: string, ...args: unknown[]) => `${key}${args.length ? `: ${args.join(', ')}` : ''}` },
-    };
-});
-
-vi.mock('../src/llm/providerService', () => ({
-    LlmProviderService: {
-        getInstance: () => ({
-            getCredentialStore: () => ({ storeApiKey: state.storeApiKey }),
-            reload: state.reload,
-            isBuiltInProviderId: (id: string) => state.builtInRoutes.has(id),
-        }),
-    },
-}));
-
-import { migrateLegacyProviders } from '../src/llm/migration';
-
-const legacy = (name: string, key: string, baseurl = 'https://example.test/v1') => ({ name, baseurl, api_key: key });
-
-beforeEach(() => {
-    state.global = {};
-    state.workspace = {};
-    state.folders = new Map([['/one', {}], ['/two', {}]]);
-    state.updates = [];
-    state.fail = undefined;
-    state.storeApiKey.mockReset().mockResolvedValue(undefined);
-    state.reload.mockReset().mockResolvedValue(undefined);
-    state.builtInRoutes = new Set(['kimi-coding']);
-});
-
-describe('legacy provider migration', () => {
-    it('stops before writes when one route has conflicting plaintext keys across scopes', async () => {
-        state.global.providers = [legacy('shared', 'one')];
-        state.folders.get('/two')!.providers = [legacy('shared', 'two')];
-        await expect(migrateLegacyProviders()).rejects.toThrow('migration.conflicts');
-        expect(state.storeApiKey).not.toHaveBeenCalled();
-        expect(state.updates).toEqual([]);
-    });
-
-    it('requires legacy custom routes that collide with built-ins to be renamed', async () => {
-        state.global.providers = [legacy('kimi-coding', 'key', 'https://proxy.example.test/v1')];
-        await expect(migrateLegacyProviders()).rejects.toThrow('migration.routeConflicts');
-        expect(state.storeApiKey).not.toHaveBeenCalled();
-    });
-
-    it('migrates all scopes, aliases exact Kimi defaults, and removes plaintext only after secure writes', async () => {
-        state.global.providers = [legacy('kimi-for-coding', 'kimi-key', 'https://api.kimi.com/coding/v1')];
-        state.workspace.providers = [legacy('proxy', 'proxy-key')];
-        state.workspace.models = { proxy: ['model-a'] };
-        state.folders.get('/one')!.providers = [legacy('folder-route', 'folder-key')];
-
-        await expect(migrateLegacyProviders()).resolves.toBe(true);
-
-        expect(state.storeApiKey.mock.calls).toEqual([
-            ['kimi-coding', 'kimi-key'], ['proxy', 'proxy-key'], ['folder-route', 'folder-key'],
-        ]);
-        expect((state.workspace.customProviders as any).proxy).toMatchObject({ models: ['model-a'], auth: 'apiKey' });
-        expect(state.global.providers).toBeUndefined();
-        expect(state.workspace.providers).toBeUndefined();
-        expect(state.folders.get('/one')!.providers).toBeUndefined();
-        const firstCleanup = state.updates.findIndex(update => update.key === 'providers' && update.value === undefined);
-        const lastCustom = state.updates.reduce((last, update, index) => update.key === 'customProviders' ? index : last, -1);
-        expect(firstCleanup).toBeGreaterThan(lastCustom);
-    });
-
-    it('restores already-cleared plaintext settings if cleanup fails midway', async () => {
-        state.global.providers = [legacy('global', 'one')];
-        state.workspace.providers = [legacy('workspace', 'two')];
-        state.fail = (_resource, key, value, target) => key === 'models' && value === undefined && target === 2;
-
-        await expect(migrateLegacyProviders()).rejects.toThrow('write failed');
-
-        expect(state.global.providers).toEqual([legacy('global', 'one')]);
-        expect(state.workspace.providers).toEqual([legacy('workspace', 'two')]);
-    });
-});
diff --git a/tests/mtmFormat.test.ts b/tests/mtmFormat.test.ts
new file mode 100644
index 0000000..3c424d4
--- /dev/null
+++ b/tests/mtmFormat.test.ts
@@ -0,0 +1,215 @@
+import { describe, expect, it, vi } from 'vitest';
+import type { AssistantMessage } from '@earendil-works/pi-ai';
+
+vi.mock('vscode', () => ({
+    EventEmitter: class {
+        event = () => ({ dispose() {} });
+        fire() {}
+        dispose() {}
+    },
+    workspace: {
+        workspaceFolders: [],
+        getConfiguration: () => ({ get: (_key: string, fallback: unknown) => fallback }),
+    },
+    Uri: {
+        parse: (value: string) => ({ scheme: value.slice(0, value.indexOf(':')) }),
+    },
+    l10n: { t: (value: string) => value },
+}));
+
+import { toPiContext } from '../src/llm/context';
+import { decodeAgentContext, encodeAgentContext, INVALID_MTM_FILE, UNSUPPORTED_MTM_FORMAT } from '../src/mtmFormat';
+import { MTM_FORMAT_VERSION, type AgentContext, type AgentMessage, type PersistedAgentMessage } from '../src/types';
+import { extractNotebookNotes, genericCellsToMessages, messagesToGenericCells } from '../src/notebook/serializer';
+import { parseUserMessageWithImages } from '../src/contextManagement/utils';
+import { hydrateProviderMessage, mergeConsecutiveUserMessages } from '../src/contextManagement/history';
+
+const assistant: AssistantMessage = {
+    role: 'assistant',
+    api: 'anthropic-messages',
+    provider: 'anthropic',
+    model: 'claude-test',
+    responseId: 'response-1',
+    stopReason: 'toolUse',
+    timestamp: 2,
+    usage: {
+        input: 1, output: 2, cacheRead: 3, cacheWrite: 4, totalTokens: 10,
+        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
+    },
+    content: [
+        { type: 'thinking', thinking: 'reason', thinkingSignature: 'signed-reason' },
+        { type: 'text', text: 'hello', textSignature: 'signed-text' },
+        { type: 'toolCall', id: 'call-1', name: 'read', arguments: { path: 'a.ts' }, thoughtSignature: 'signed-tool' },
+    ],
+};
+
+function context(messages: PersistedAgentMessage[]): AgentContext {
+    return {
+        formatVersion: MTM_FORMAT_VERSION,
+        metadata: {
+            uuid: 'agent-1', name: 'Agent', created_at: '2026-01-01T00:00:00.000Z',
+            parent_agent_id: null, allowed_uris: ['/'], provider: 'anthropic', model: 'claude-test',
+        },
+        context: messages,
+    };
+}
+
+describe(`.mtm format version ${MTM_FORMAT_VERSION}`, () => {
+    it('round-trips native signed assistant and tool-result messages without replay duplication', () => {
+        const source = context([
+            { role: 'user', content: 'read it', timestamp: 1, mutsumi: { ghostBlock: { files: [], tools: [] } } },
+            assistant,
+            {
+                role: 'toolResult', toolCallId: 'call-1', toolName: 'read',
+                content: [{ type: 'text', text: 'contents' }], isError: false, timestamp: 3,
+            },
+            { role: 'user', content: [{ type: 'text', text: 'look' }, { type: 'image', mimeType: 'image/png', data: 'AQID' }], timestamp: 4 },
+        ]);
+        const decoded = decodeAgentContext(encodeAgentContext(source));
+        expect(decoded).toEqual(source);
+        expect(JSON.stringify(decoded)).not.toContain('piAiReplay');
+        expect(JSON.stringify(decoded)).not.toContain('tool_calls');
+
+        const notebookRoundTrip = genericCellsToMessages(messagesToGenericCells(source.context));
+        expect(notebookRoundTrip).toEqual(source.context);
+    });
+
+    it('rejects unversioned and old-shaped messages', () => {
+        expect(() => decodeAgentContext(new TextEncoder().encode(JSON.stringify({ metadata: {}, context: [] }))))
+            .toThrow(expect.objectContaining({ code: UNSUPPORTED_MTM_FORMAT }));
+        const unsupportedVersion = MTM_FORMAT_VERSION + 1;
+        const wrongVersion = { ...context([]), formatVersion: unsupportedVersion };
+        expect(() => decodeAgentContext(new TextEncoder().encode(JSON.stringify(wrongVersion))))
+            .toThrow(expect.objectContaining({ code: UNSUPPORTED_MTM_FORMAT, actualVersion: unsupportedVersion }));
+        const old = context([]) as any;
+        old.context = [{ role: 'tool', tool_call_id: 'call-1', content: 'old' }];
+        expect(() => decodeAgentContext(new TextEncoder().encode(JSON.stringify(old))))
+            .toThrow(expect.objectContaining({ code: INVALID_MTM_FILE }));
+
+        const missingCore = context([{ role: 'user', content: 'go', timestamp: 1 }, { ...assistant, model: undefined } as any]);
+        expect(() => decodeAgentContext(new TextEncoder().encode(JSON.stringify(missingCore))))
+            .toThrow(expect.objectContaining({ code: INVALID_MTM_FILE }));
+        const incompleteToolTurn = context([{ role: 'user', content: 'go', timestamp: 1 }, assistant]);
+        expect(() => decodeAgentContext(new TextEncoder().encode(JSON.stringify(incompleteToolTurn))))
+            .toThrow('ends before all tool calls have results');
+
+        const removedProvider = context([]) as any;
+        removedProvider.metadata.provider = 'kimi-for-coding';
+        expect(() => decodeAgentContext(new TextEncoder().encode(JSON.stringify(removedProvider))))
+            .toThrow('removed provider ID');
+    });
+
+    it('round-trips Markup notes at every user-relative anchor without adding messages', () => {
+        const source = context([
+            { role: 'user', content: 'one', timestamp: 1 },
+            { role: 'user', content: [{ type: 'text', text: 'two' }, { type: 'image', mimeType: 'image/png', data: 'AQID' }], timestamp: 2 },
+        ]);
+        source.notes = [
+            { beforeUserIndex: 0, markdown: '# before' },
+            { beforeUserIndex: 1, markdown: '' },
+            { beforeUserIndex: 1, markdown: 'second in gap' },
+            { beforeUserIndex: 2, markdown: 'after' },
+        ];
+
+        const decoded = decodeAgentContext(encodeAgentContext(source));
+        expect(decoded).toEqual(source);
+        const cells = messagesToGenericCells(decoded.context, decoded.notes);
+        expect(cells.map(cell => [cell.kind, cell.value])).toEqual([
+            [1, '# before'], [2, 'one'], [1, ''], [1, 'second in gap'],
+            [2, 'two![image](data:image/png;base64,AQID)'], [1, 'after'],
+        ]);
+        expect(genericCellsToMessages(cells)).toEqual(source.context);
+        expect(extractNotebookNotes(cells)).toEqual(source.notes);
+    });
+
+    it('allows consecutive pending users but still rejects a user inside an open tool turn', () => {
+        const pending = context([
+            { role: 'user', content: 'first', timestamp: 1 },
+            { role: 'user', content: 'second', timestamp: 2 },
+        ]);
+        expect(decodeAgentContext(encodeAgentContext(pending))).toEqual(pending);
+        expect(messagesToGenericCells(pending.context)).toHaveLength(2);
+
+        const dangling = context([
+            { role: 'user', content: 'first', timestamp: 1 },
+            assistant,
+            { role: 'user', content: 'not allowed yet', timestamp: 3 },
+        ]);
+        expect(() => encodeAgentContext(dangling)).toThrow('unexpected user message');
+    });
+
+    it('keeps a notebook user pending when its interaction metadata is malformed', () => {
+        const cells = [{
+            kind: 2 as const,
+            value: 'retry me',
+            metadata: {
+                role: 'user' as const,
+                timestamp: 7,
+                mutsumi_interaction: [{ role: 'assistant', content: [], api: 'x' }] as any,
+            },
+        }];
+        expect(genericCellsToMessages(cells)).toEqual([
+            { role: 'user', content: 'retry me', timestamp: 7 },
+        ]);
+    });
+
+    it('preserves arbitrary non-core provider fields and hydrates only a temporary provider copy', () => {
+        const rawAssistant = {
+            role: 'assistant' as const,
+            api: 'anthropic-messages', provider: 'anthropic', model: 'claude-test',
+            content: [{ type: 'text' as const, text: 'hello', textSignature: { provider: 'changed' } }],
+            usage: { providerSpecific: true }, timestamp: 'yesterday', stopReason: { native: true },
+            responseId: { nested: true }, diagnostics: 'opaque',
+            nativeFutureField: { any: ['JSON', 1] },
+        };
+        const source = context([{ role: 'user', content: 'go' }, rawAssistant]);
+        const decoded = decodeAgentContext(encodeAgentContext(source));
+        expect(decoded).toEqual(source);
+
+        const hydrated = hydrateProviderMessage(decoded.context[1]);
+        expect(hydrated).toMatchObject({ timestamp: 0, stopReason: 'stop' });
+        expect((hydrated as any).usage).toEqual({
+            input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0,
+            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
+        });
+        expect(decoded.context[1]).toEqual(rawAssistant);
+    });
+
+    it('merges only adjacent provider-facing users and preserves multimodal order', () => {
+        const mergedText = mergeConsecutiveUserMessages([
+            { role: 'user', content: 'one', timestamp: 1 },
+            { role: 'user', content: 'two', timestamp: 2 },
+        ]);
+        expect(mergedText).toEqual([{ role: 'user', content: 'one\n\ntwo', timestamp: 2 }]);
+
+        const mergedMulti = mergeConsecutiveUserMessages([
+            { role: 'user', content: [{ type: 'image', mimeType: 'image/png', data: 'A' }], timestamp: 1 },
+            { role: 'user', content: 'caption', timestamp: 2 },
+            assistant,
+            { role: 'user', content: 'next round', timestamp: 3 },
+        ]);
+        expect(mergedMulti[0]).toEqual({
+            role: 'user', timestamp: 2, content: [
+                { type: 'image', mimeType: 'image/png', data: 'A' },
+                { type: 'text', text: '\n\n' },
+                { type: 'text', text: 'caption' },
+            ],
+        });
+        expect(mergedMulti).toHaveLength(3);
+    });
+
+    it('passes native messages directly to pi-ai while stripping Mutsumi-only user state', async () => {
+        const user: AgentMessage = {
+            role: 'user', content: [{ type: 'image', mimeType: 'image/png', data: 'AQID' }], timestamp: 1,
+            mutsumi: { ghostBlock: { files: [], tools: [] } },
+        };
+        const piContext = toPiContext('rules', [user, assistant]);
+        expect(piContext.systemPrompt).toBe('rules');
+        expect(piContext.messages[0]).toEqual({ role: 'user', content: user.content, timestamp: 1 });
+        expect(piContext.messages[1]).toBe(assistant);
+
+        await expect(parseUserMessageWithImages('![image](data:image/png;base64,AQID)')).resolves.toEqual([
+            { type: 'image', mimeType: 'image/png', data: 'AQID' },
+        ]);
+    });
+});
diff --git a/tests/providerService.test.ts b/tests/providerService.test.ts
index d4c203f..8754904 100644
--- a/tests/providerService.test.ts
+++ b/tests/providerService.test.ts
@@ -33,12 +33,12 @@ afterEach(() => {
 });
 
 describe('LlmProviderService registry', () => {
-    it('loads the built-in catalog and preserves the legacy Kimi alias', async () => {
+    it('loads the built-in catalog and rejects the removed legacy Kimi provider ID', async () => {
         const service = new LlmProviderService();
         await service.initialize(context());
-        const selection = service.resolveSelection({ provider: 'kimi-for-coding', model: 'kimi-for-coding' });
-        expect(selection.provider).toBe('kimi-coding');
+        const selection = service.resolveSelection({ provider: 'kimi-coding', model: 'kimi-for-coding' });
         expect(selection.modelInfo.input).toContain('image');
+        expect(() => service.resolveSelection({ provider: 'kimi-for-coding', model: 'kimi-for-coding' })).toThrow('not available');
     });
 
     it('rejects custom route collisions without replacing the previous registry', async () => {
@@ -53,7 +53,7 @@ describe('LlmProviderService registry', () => {
     });
 
     it.each([
-        [{ 'kimi-for-coding': { baseUrl: 'https://example.test/v1' } }, 'conflicts with a built-in provider'],
+        [{ 'kimi-for-coding': { baseUrl: 'https://example.test/v1' } }, 'uses a removed provider ID'],
         [{ local: { baseUrl: 'file:///tmp/models' } }, 'must use HTTP(S)'],
         [{ local: { baseUrl: 'https://user:secret@example.test/v1' } }, 'must not contain credentials'],
     ])('rejects unsafe or conflicting custom configuration', async (profiles, message) => {
diff --git a/tests/replayAndContext.test.ts b/tests/replayAndContext.test.ts
deleted file mode 100644
index 61c60f3..0000000
--- a/tests/replayAndContext.test.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { describe, expect, it } from 'vitest';
-import type { AssistantMessage } from '@earendil-works/pi-ai';
-import { toPiContext } from '../src/llm/context';
-import { toPiAssistant, toReplayState } from '../src/llm/replay';
-import type { AgentMessage } from '../src/types';
-
-const native: AssistantMessage = {
-    role: 'assistant', api: 'anthropic-messages', provider: 'anthropic', model: 'claude-test',
-    stopReason: 'toolUse', timestamp: 1,
-    usage: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0, totalTokens: 3, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
-    content: [
-        { type: 'thinking', thinking: 'reason', thinkingSignature: 'signed-reason' },
-        { type: 'text', text: 'hello', textSignature: 'signed-text' },
-        { type: 'toolCall', id: 'call-1', name: 'read', arguments: { path: 'a.ts' }, thoughtSignature: 'signed-tool' },
-    ],
-};
-
-describe('pi-ai replay state', () => {
-    it('round-trips signed native blocks when visible content still matches', () => {
-        const message: AgentMessage = {
-            role: 'assistant', content: 'hello', reasoning_content: 'reason',
-            tool_calls: [{ id: 'call-1', type: 'function', function: { name: 'read', arguments: '{"path":"a.ts"}' } }],
-            metadata: { piAiReplay: toReplayState(native) },
-        };
-        expect(toPiAssistant(message)).toMatchObject({
-            api: 'anthropic-messages', provider: 'anthropic', model: 'claude-test',
-            content: [
-                { type: 'thinking', thinkingSignature: 'signed-reason' },
-                { type: 'text', textSignature: 'signed-text' },
-                { type: 'toolCall', thoughtSignature: 'signed-tool' },
-            ],
-        });
-    });
-
-    it('drops signatures and treats edited or corrupt metadata as a foreign assistant', () => {
-        const message: AgentMessage = {
-            role: 'assistant', content: 'edited', reasoning_content: 'reason',
-            metadata: { piAiReplay: toReplayState(native) },
-        };
-        const converted = toPiAssistant(message);
-        expect(converted.api).toBe('mutsumi-foreign');
-        expect(converted.content).toEqual([
-            { type: 'thinking', thinking: 'reason' },
-            { type: 'text', text: 'edited' },
-        ]);
-    });
-});
-
-describe('provider-neutral context conversion', () => {
-    it('converts system, image, tools, and tool error semantics', () => {
-        const context = toPiContext([
-            { role: 'system', content: 'rules' },
-            { role: 'user', content: [
-                { type: 'text', text: 'look' },
-                { type: 'image_url', image_url: { url: 'data:image/png;base64,AQID' } },
-            ] },
-            { role: 'tool', name: 'read', tool_call_id: 'call-1', content: 'Error: missing' },
-        ], [{ type: 'function', function: { name: 'read', description: 'Read', parameters: { type: 'object' } } }]);
-
-        expect(context.systemPrompt).toBe('rules');
-        expect(context.messages[0]).toMatchObject({ role: 'user', content: [
-            { type: 'text', text: 'look' },
-            { type: 'image', mimeType: 'image/png', data: 'AQID' },
-        ] });
-        expect(context.messages[1]).toMatchObject({ role: 'toolResult', isError: true });
-        expect(context.tools?.[0]).toMatchObject({ name: 'read', parameters: { type: 'object' } });
-    });
-});