diff --git a/.changeset/bright-llamas-enter.md b/.changeset/bright-llamas-enter.md new file mode 100644 index 00000000..1e77510a --- /dev/null +++ b/.changeset/bright-llamas-enter.md @@ -0,0 +1,12 @@ +--- +"task-master-ai": patch +--- + +Fix expand command preserving tagged task structure and preventing data corruption + +- Enhance E2E tests with comprehensive tag-aware expand testing to verify tag corruption fix +- Add new test section for feature-expand tag creation and testing during expand operations +- Verify tag preservation during expand, force expand, and expand --all operations +- Test that master tag remains intact while feature-expand tag receives subtasks correctly +- Fix file path references to use correct .taskmaster/config.json and .taskmaster/tasks/tasks.json locations +- All tag corruption verification tests pass successfully, confirming the expand command tag corruption bug fix works as expected diff --git a/.changeset/bright-monkeys-act.md b/.changeset/bright-monkeys-act.md new file mode 100644 index 00000000..8536974c --- /dev/null +++ b/.changeset/bright-monkeys-act.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Ensure projectRoot is a string (potential WSL fix) diff --git a/.changeset/chatty-rats-talk.md b/.changeset/chatty-rats-talk.md new file mode 100644 index 00000000..6a6e7ad5 --- /dev/null +++ b/.changeset/chatty-rats-talk.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Fix Cursor deeplink installation by providing copy-paste instructions for GitHub compatibility diff --git a/.changeset/chubby-needles-beam.md b/.changeset/chubby-needles-beam.md new file mode 100644 index 00000000..422215c8 --- /dev/null +++ b/.changeset/chubby-needles-beam.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Fix bulk update tag corruption in tagged task lists diff --git a/.changeset/flat-geckos-enjoy.md b/.changeset/flat-geckos-enjoy.md new file mode 100644 index 00000000..57967cd2 --- /dev/null +++ b/.changeset/flat-geckos-enjoy.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Include additional Anthropic models running on Bedrock in what is supported diff --git a/.changeset/hot-planets-deny.md b/.changeset/hot-planets-deny.md new file mode 100644 index 00000000..0399324f --- /dev/null +++ b/.changeset/hot-planets-deny.md @@ -0,0 +1,7 @@ +--- +"task-master-ai": patch +--- + +Fix expand-task to use tag-specific complexity reports + +The expand-task function now correctly uses complexity reports specific to the current tag context (e.g., task-complexity-report_feature-branch.json) instead of always using the default task-complexity-report.json file. This enables proper task expansion behavior when working with multiple tag contexts. diff --git a/.changeset/huge-moose-prove.md b/.changeset/huge-moose-prove.md new file mode 100644 index 00000000..f45e24fb --- /dev/null +++ b/.changeset/huge-moose-prove.md @@ -0,0 +1,8 @@ +--- +"task-master-ai": minor +--- + +Can now configure baseURL of provider with `_BASE_URL` + +- For example: + - `OPENAI_BASE_URL` diff --git a/.changeset/icy-dryers-hunt.md b/.changeset/icy-dryers-hunt.md new file mode 100644 index 00000000..0be2f1e0 --- /dev/null +++ b/.changeset/icy-dryers-hunt.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Call rules interactive setup during init diff --git a/.changeset/large-wolves-strive.md b/.changeset/large-wolves-strive.md new file mode 100644 index 00000000..f170b09a --- /dev/null +++ b/.changeset/large-wolves-strive.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Update o3 model price diff --git a/.changeset/lemon-deer-hide.md b/.changeset/lemon-deer-hide.md new file mode 100644 index 00000000..b63641b1 --- /dev/null +++ b/.changeset/lemon-deer-hide.md @@ -0,0 +1,17 @@ +--- +'task-master-ai': minor +--- + +Added comprehensive rule profile management: + +**New Profile Support**: Added comprehensive IDE profile support with eight specialized profiles: Claude Code, Cline, Codex, Cursor, Roo, Trae, VS Code, and Windsurf. Each profile is optimized for its respective IDE with appropriate mappings and configuration. +**Initialization**: You can now specify which rule profiles to include at project initialization using `--rules ` or `-r ` (e.g., `task-master init -r cursor,roo`). Only the selected profiles and configuration are included. +**Add/Remove Commands**: `task-master rules add ` and `task-master rules remove ` let you manage specific rule profiles and MCP config after initialization, supporting multiple profiles at once. +**Interactive Setup**: `task-master rules setup` launches an interactive prompt to select which rule profiles to add to your project. This does **not** re-initialize your project or affect shell aliases; it only manages rules. +**Selective Removal**: Rules removal intelligently preserves existing non-Task Master rules and files and only removes Task Master-specific rules. Profile directories are only removed when completely empty and all conditions are met (no existing rules, no other files/folders, MCP config completely removed). +**Safety Features**: Confirmation messages clearly explain that only Task Master-specific rules and MCP configurations will be removed, while preserving existing custom rules and other files. +**Robust Validation**: Includes comprehensive checks for array types in MCP config processing and error handling throughout the rules management system. + +This enables more flexible, rule-specific project setups with intelligent cleanup that preserves user customizations while safely managing Task Master components. + +- Resolves #338 diff --git a/.changeset/major-dogs-admire.md b/.changeset/major-dogs-admire.md new file mode 100644 index 00000000..f4cc8461 --- /dev/null +++ b/.changeset/major-dogs-admire.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Fix .gitignore missing trailing newline during project initialization diff --git a/.changeset/mean-papayas-share.md b/.changeset/mean-papayas-share.md new file mode 100644 index 00000000..4cf29b1a --- /dev/null +++ b/.changeset/mean-papayas-share.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Default to Cursor profile for MCP init when no rules specified diff --git a/.changeset/modern-cats-pick.md b/.changeset/modern-cats-pick.md new file mode 100644 index 00000000..056c22f1 --- /dev/null +++ b/.changeset/modern-cats-pick.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Improves Amazon Bedrock support diff --git a/.changeset/moody-goats-leave.md b/.changeset/moody-goats-leave.md new file mode 100644 index 00000000..0fc81384 --- /dev/null +++ b/.changeset/moody-goats-leave.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": minor +--- + +Adds support for gemini-cli as a provider, enabling free or subscription use through Google Accounts and paid Gemini Cloud Assist (GCA) subscriptions. diff --git a/.changeset/nasty-berries-tan.md b/.changeset/nasty-berries-tan.md new file mode 100644 index 00000000..4eb91824 --- /dev/null +++ b/.changeset/nasty-berries-tan.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Fix issues with task creation/update where subtasks are being created like id: . instead if just id: diff --git a/.changeset/nasty-chefs-add.md b/.changeset/nasty-chefs-add.md new file mode 100644 index 00000000..304aeb24 --- /dev/null +++ b/.changeset/nasty-chefs-add.md @@ -0,0 +1,8 @@ +--- +"task-master-ai": patch +--- + +Fixes issue with expand CLI command "Complexity report not found" + +- Closes #735 +- Closes #728 diff --git a/.changeset/olive-clouds-tan.md b/.changeset/olive-clouds-tan.md new file mode 100644 index 00000000..7a2b184e --- /dev/null +++ b/.changeset/olive-clouds-tan.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Fix data corruption issues by ensuring project root and tag information is properly passed through all command operations diff --git a/.changeset/petite-friends-arrive.md b/.changeset/petite-friends-arrive.md new file mode 100644 index 00000000..d1fc7012 --- /dev/null +++ b/.changeset/petite-friends-arrive.md @@ -0,0 +1,10 @@ +--- +"task-master-ai": minor +--- + +Make task-master more compatible with the "o" family models of OpenAI + +Now works well with: +- o3 +- o3-mini +- etc. diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 00000000..0e58b3c5 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,23 @@ +{ + "mode": "exit", + "tag": "rc", + "initialVersions": { + "task-master-ai": "0.17.1" + }, + "changesets": [ + "bright-llamas-enter", + "huge-moose-prove", + "icy-dryers-hunt", + "lemon-deer-hide", + "modern-cats-pick", + "nasty-berries-tan", + "shy-groups-fly", + "sour-lions-check", + "spicy-teams-travel", + "stale-cameras-sin", + "swift-squids-sip", + "tiny-dogs-change", + "vast-plants-exist", + "wet-berries-dress" + ] +} diff --git a/.changeset/shy-groups-fly.md b/.changeset/shy-groups-fly.md new file mode 100644 index 00000000..e645fe31 --- /dev/null +++ b/.changeset/shy-groups-fly.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": minor +--- + +Add better support for python projects by adding `pyproject.toml` as a projectRoot marker diff --git a/.changeset/smooth-ants-live.md b/.changeset/smooth-ants-live.md new file mode 100644 index 00000000..9f16c993 --- /dev/null +++ b/.changeset/smooth-ants-live.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": minor +--- + +Added option for the AI to determine the number of tasks required based entirely on complexity diff --git a/.changeset/sour-lions-check.md b/.changeset/sour-lions-check.md new file mode 100644 index 00000000..03053f1b --- /dev/null +++ b/.changeset/sour-lions-check.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Store tasks in Git by default diff --git a/.changeset/spicy-teams-travel.md b/.changeset/spicy-teams-travel.md new file mode 100644 index 00000000..b9551e5a --- /dev/null +++ b/.changeset/spicy-teams-travel.md @@ -0,0 +1,11 @@ +--- +"task-master-ai": patch +--- + +Improve provider validation system with clean constants structure + +- **Fixed "Invalid provider hint" errors**: Resolved validation failures for Azure, Vertex, and Bedrock providers +- **Improved search UX**: Integrated search for better model discovery with real-time filtering +- **Better organization**: Moved custom provider options to bottom of model selection with clear section separators + +This change ensures all custom providers (Azure, Vertex, Bedrock, OpenRouter, Ollama) work correctly in `task-master models --setup` diff --git a/.changeset/stale-cameras-sin.md b/.changeset/stale-cameras-sin.md new file mode 100644 index 00000000..e13e1997 --- /dev/null +++ b/.changeset/stale-cameras-sin.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Fix weird `task-master init` bug when using in certain environments diff --git a/.changeset/sweet-ties-argue.md b/.changeset/sweet-ties-argue.md new file mode 100644 index 00000000..1c46fc11 --- /dev/null +++ b/.changeset/sweet-ties-argue.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": minor +--- + +Add advanced settings for Claude Code AI Provider diff --git a/.changeset/swift-squids-sip.md b/.changeset/swift-squids-sip.md new file mode 100644 index 00000000..ed53470c --- /dev/null +++ b/.changeset/swift-squids-sip.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Rename Roo Code Boomerang role to Orchestrator diff --git a/.changeset/tame-vans-throw.md b/.changeset/tame-vans-throw.md new file mode 100644 index 00000000..53c6ccfc --- /dev/null +++ b/.changeset/tame-vans-throw.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +fixes a critical issue where subtask generation fails on gemini-2.5-pro unless explicitly prompted to return 'details' field as a string not an object diff --git a/.changeset/tidy-meals-enter.md b/.changeset/tidy-meals-enter.md new file mode 100644 index 00000000..5b3667b9 --- /dev/null +++ b/.changeset/tidy-meals-enter.md @@ -0,0 +1,5 @@ +--- +'task-master-ai': patch +--- + +Support custom response language diff --git a/.changeset/tiny-dogs-change.md b/.changeset/tiny-dogs-change.md new file mode 100644 index 00000000..0396f2f4 --- /dev/null +++ b/.changeset/tiny-dogs-change.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Improve mcp keys check in cursor diff --git a/.changeset/vast-plants-exist.md b/.changeset/vast-plants-exist.md new file mode 100644 index 00000000..40190f44 --- /dev/null +++ b/.changeset/vast-plants-exist.md @@ -0,0 +1,22 @@ +--- +"task-master-ai": minor +--- + +- **Git Worktree Detection:** + - Now properly skips Git initialization when inside existing Git worktree + - Prevents accidental nested repository creation +- **Flag System Overhaul:** + - `--git`/`--no-git` controls repository initialization + - `--aliases`/`--no-aliases` consistently manages shell alias creation + - `--git-tasks`/`--no-git-tasks` controls whether task files are stored in Git + - `--dry-run` accurately previews all initialization behaviors +- **GitTasks Functionality:** + - New `--git-tasks` flag includes task files in Git (comments them out in .gitignore) + - New `--no-git-tasks` flag excludes task files from Git (default behavior) + - Supports both CLI and MCP interfaces with proper parameter passing + +**Implementation Details:** +- Added explicit Git worktree detection before initialization +- Refactored flag processing to ensure consistent behavior + +- Fixes #734 \ No newline at end of file diff --git a/.changeset/wet-berries-dress.md b/.changeset/wet-berries-dress.md new file mode 100644 index 00000000..a4fcef16 --- /dev/null +++ b/.changeset/wet-berries-dress.md @@ -0,0 +1,22 @@ +--- +"task-master-ai": minor +--- + +Add Claude Code provider support + +Introduces a new provider that enables using Claude models (Opus and Sonnet) through the Claude Code CLI without requiring an API key. + +Key features: +- New claude-code provider with support for opus and sonnet models +- No API key required - uses local Claude Code CLI installation +- Optional dependency - won't affect users who don't need Claude Code +- Lazy loading ensures the provider only loads when requested +- Full integration with existing Task Master commands and workflows +- Comprehensive test coverage for reliability +- New --claude-code flag for the models command + +Users can now configure Claude Code models with: + task-master models --set-main sonnet --claude-code + task-master models --set-research opus --claude-code + +The @anthropic-ai/claude-code package is optional and won't be installed unless explicitly needed. diff --git a/.changeset/wicked-rats-hide.md b/.changeset/wicked-rats-hide.md new file mode 100644 index 00000000..bc95d520 --- /dev/null +++ b/.changeset/wicked-rats-hide.md @@ -0,0 +1,5 @@ +--- +"task-master-ai": patch +--- + +Fix rules command to use reliable project root detection like other commands diff --git a/.cursor/rules/dev_workflow.mdc b/.cursor/rules/dev_workflow.mdc index 741b1ade..ec2b326b 100644 --- a/.cursor/rules/dev_workflow.mdc +++ b/.cursor/rules/dev_workflow.mdc @@ -153,7 +153,7 @@ When users initialize Taskmaster on existing projects: 4. **Tag-Based Organization**: Parse PRDs into appropriate tags (`refactor-api`, `feature-dashboard`, `tech-debt`, etc.) 5. **Master List Curation**: Keep only the most valuable initiatives in master -The parse-prd's `--append` flag enables the user to parse multple PRDs within tags or across tags. PRDs should be focused and the number of tasks they are parsed into should be strategically chosen relative to the PRD's complexity and level of detail. +The parse-prd's `--append` flag enables the user to parse multiple PRDs within tags or across tags. PRDs should be focused and the number of tasks they are parsed into should be strategically chosen relative to the PRD's complexity and level of detail. ### Workflow Transition Examples diff --git a/.cursor/rules/taskmaster.mdc b/.cursor/rules/taskmaster.mdc index 44a8b349..3fc236f3 100644 --- a/.cursor/rules/taskmaster.mdc +++ b/.cursor/rules/taskmaster.mdc @@ -272,7 +272,7 @@ This document provides a detailed reference for interacting with Taskmaster, cov * **CLI Command:** `task-master clear-subtasks [options]` * **Description:** `Remove all subtasks from one or more specified Taskmaster parent tasks.` * **Key Parameters/Options:** - * `id`: `The ID(s) of the Taskmaster parent task(s) whose subtasks you want to remove, e.g., '15' or '16,18'. Required unless using `all`.) (CLI: `-i, --id `) + * `id`: `The ID(s) of the Taskmaster parent task(s) whose subtasks you want to remove, e.g., '15' or '16,18'. Required unless using 'all'.` (CLI: `-i, --id `) * `all`: `Tell Taskmaster to remove subtasks from all parent tasks.` (CLI: `--all`) * `tag`: `Specify which tag context to operate on. Defaults to the current active tag.` (CLI: `--tag `) * `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file `) diff --git a/.taskmaster/config.json b/.taskmaster/config.json index 3bd2b3f8..74780437 100644 --- a/.taskmaster/config.json +++ b/.taskmaster/config.json @@ -29,6 +29,8 @@ "bedrockBaseURL": "https://bedrock.us-east-1.amazonaws.com", "userId": "1234567890", "azureBaseURL": "https://your-endpoint.azure.com/", - "defaultTag": "master" - } + "defaultTag": "master", + "responseLanguage": "English" + }, + "claudeCode": {} } diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fc97795..13351fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -219,6 +219,110 @@ - [#789](https://github.com/eyaltoledano/claude-task-master/pull/789) [`8cde6c2`](https://github.com/eyaltoledano/claude-task-master/commit/8cde6c27087f401d085fe267091ae75334309d96) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix contextGatherer bug when adding a task `Cannot read properties of undefined (reading 'forEach')` +## 0.18.0-rc.0 + +### Minor Changes + +- [#830](https://github.com/eyaltoledano/claude-task-master/pull/830) [`e9d1bc2`](https://github.com/eyaltoledano/claude-task-master/commit/e9d1bc2385521c08374a85eba7899e878a51066c) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Can now configure baseURL of provider with `_BASE_URL` + + - For example: + - `OPENAI_BASE_URL` + +- [#460](https://github.com/eyaltoledano/claude-task-master/pull/460) [`a09a2d0`](https://github.com/eyaltoledano/claude-task-master/commit/a09a2d0967a10276623e3f3ead3ed577c15ce62f) Thanks [@joedanz](https://github.com/joedanz)! - Added comprehensive rule profile management: + + **New Profile Support**: Added comprehensive IDE profile support with eight specialized profiles: Claude Code, Cline, Codex, Cursor, Roo, Trae, VS Code, and Windsurf. Each profile is optimized for its respective IDE with appropriate mappings and configuration. + **Initialization**: You can now specify which rule profiles to include at project initialization using `--rules ` or `-r ` (e.g., `task-master init -r cursor,roo`). Only the selected profiles and configuration are included. + **Add/Remove Commands**: `task-master rules add ` and `task-master rules remove ` let you manage specific rule profiles and MCP config after initialization, supporting multiple profiles at once. + **Interactive Setup**: `task-master rules setup` launches an interactive prompt to select which rule profiles to add to your project. This does **not** re-initialize your project or affect shell aliases; it only manages rules. + **Selective Removal**: Rules removal intelligently preserves existing non-Task Master rules and files and only removes Task Master-specific rules. Profile directories are only removed when completely empty and all conditions are met (no existing rules, no other files/folders, MCP config completely removed). + **Safety Features**: Confirmation messages clearly explain that only Task Master-specific rules and MCP configurations will be removed, while preserving existing custom rules and other files. + **Robust Validation**: Includes comprehensive checks for array types in MCP config processing and error handling throughout the rules management system. + + This enables more flexible, rule-specific project setups with intelligent cleanup that preserves user customizations while safely managing Task Master components. + + - Resolves #338 + +- [#804](https://github.com/eyaltoledano/claude-task-master/pull/804) [`1b8c320`](https://github.com/eyaltoledano/claude-task-master/commit/1b8c320c570473082f1eb4bf9628bff66e799092) Thanks [@ejones40](https://github.com/ejones40)! - Add better support for python projects by adding `pyproject.toml` as a projectRoot marker + +- [#743](https://github.com/eyaltoledano/claude-task-master/pull/743) [`a2a3229`](https://github.com/eyaltoledano/claude-task-master/commit/a2a3229fd01e24a5838f11a3938a77250101e184) Thanks [@joedanz](https://github.com/joedanz)! - - **Git Worktree Detection:** + + - Now properly skips Git initialization when inside existing Git worktree + - Prevents accidental nested repository creation + - **Flag System Overhaul:** + - `--git`/`--no-git` controls repository initialization + - `--aliases`/`--no-aliases` consistently manages shell alias creation + - `--git-tasks`/`--no-git-tasks` controls whether task files are stored in Git + - `--dry-run` accurately previews all initialization behaviors + - **GitTasks Functionality:** + - New `--git-tasks` flag includes task files in Git (comments them out in .gitignore) + - New `--no-git-tasks` flag excludes task files from Git (default behavior) + - Supports both CLI and MCP interfaces with proper parameter passing + + **Implementation Details:** + + - Added explicit Git worktree detection before initialization + - Refactored flag processing to ensure consistent behavior + - Fixes #734 + +- [#829](https://github.com/eyaltoledano/claude-task-master/pull/829) [`4b0c9d9`](https://github.com/eyaltoledano/claude-task-master/commit/4b0c9d9af62d00359fca3f43283cf33223d410bc) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add Claude Code provider support + + Introduces a new provider that enables using Claude models (Opus and Sonnet) through the Claude Code CLI without requiring an API key. + + Key features: + + - New claude-code provider with support for opus and sonnet models + - No API key required - uses local Claude Code CLI installation + - Optional dependency - won't affect users who don't need Claude Code + - Lazy loading ensures the provider only loads when requested + - Full integration with existing Task Master commands and workflows + - Comprehensive test coverage for reliability + - New --claude-code flag for the models command + + Users can now configure Claude Code models with: + task-master models --set-main sonnet --claude-code + task-master models --set-research opus --claude-code + + The @anthropic-ai/claude-code package is optional and won't be installed unless explicitly needed. + +### Patch Changes + +- [#827](https://github.com/eyaltoledano/claude-task-master/pull/827) [`5da5b59`](https://github.com/eyaltoledano/claude-task-master/commit/5da5b59bdeeb634dcb3adc7a9bc0fc37e004fa0c) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix expand command preserving tagged task structure and preventing data corruption + + - Enhance E2E tests with comprehensive tag-aware expand testing to verify tag corruption fix + - Add new test section for feature-expand tag creation and testing during expand operations + - Verify tag preservation during expand, force expand, and expand --all operations + - Test that master tag remains intact while feature-expand tag receives subtasks correctly + - Fix file path references to use correct .taskmaster/config.json and .taskmaster/tasks/tasks.json locations + - All tag corruption verification tests pass successfully, confirming the expand command tag corruption bug fix works as expected + +- [#833](https://github.com/eyaltoledano/claude-task-master/pull/833) [`cf2c066`](https://github.com/eyaltoledano/claude-task-master/commit/cf2c06697a0b5b952fb6ca4b3c923e9892604d08) Thanks [@joedanz](https://github.com/joedanz)! - Call rules interactive setup during init + +- [#826](https://github.com/eyaltoledano/claude-task-master/pull/826) [`7811227`](https://github.com/eyaltoledano/claude-task-master/commit/78112277b3caa4539e6e29805341a944799fb0e7) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Improves Amazon Bedrock support + +- [#834](https://github.com/eyaltoledano/claude-task-master/pull/834) [`6483537`](https://github.com/eyaltoledano/claude-task-master/commit/648353794eb60d11ffceda87370a321ad310fbd7) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix issues with task creation/update where subtasks are being created like id: . instead if just id: + +- [#835](https://github.com/eyaltoledano/claude-task-master/pull/835) [`727f1ec`](https://github.com/eyaltoledano/claude-task-master/commit/727f1ec4ebcbdd82547784c4c113b666af7e122e) Thanks [@joedanz](https://github.com/joedanz)! - Store tasks in Git by default + +- [#822](https://github.com/eyaltoledano/claude-task-master/pull/822) [`1bd6d4f`](https://github.com/eyaltoledano/claude-task-master/commit/1bd6d4f2468070690e152e6e63e15a57bc550d90) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Improve provider validation system with clean constants structure + + - **Fixed "Invalid provider hint" errors**: Resolved validation failures for Azure, Vertex, and Bedrock providers + - **Improved search UX**: Integrated search for better model discovery with real-time filtering + - **Better organization**: Moved custom provider options to bottom of model selection with clear section separators + + This change ensures all custom providers (Azure, Vertex, Bedrock, OpenRouter, Ollama) work correctly in `task-master models --setup` + +- [#633](https://github.com/eyaltoledano/claude-task-master/pull/633) [`3a2325a`](https://github.com/eyaltoledano/claude-task-master/commit/3a2325a963fed82377ab52546eedcbfebf507a7e) Thanks [@nmarley](https://github.com/nmarley)! - Fix weird `task-master init` bug when using in certain environments + +- [#831](https://github.com/eyaltoledano/claude-task-master/pull/831) [`b592dff`](https://github.com/eyaltoledano/claude-task-master/commit/b592dff8bc5c5d7966843fceaa0adf4570934336) Thanks [@joedanz](https://github.com/joedanz)! - Rename Roo Code Boomerang role to Orchestrator + +- [#830](https://github.com/eyaltoledano/claude-task-master/pull/830) [`e9d1bc2`](https://github.com/eyaltoledano/claude-task-master/commit/e9d1bc2385521c08374a85eba7899e878a51066c) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Improve mcp keys check in cursor + +## 0.17.1 + +### Patch Changes + +- [#789](https://github.com/eyaltoledano/claude-task-master/pull/789) [`8cde6c2`](https://github.com/eyaltoledano/claude-task-master/commit/8cde6c27087f401d085fe267091ae75334309d96) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix contextGatherer bug when adding a task `Cannot read properties of undefined (reading 'forEach')` + ## 0.17.0 ### Minor Changes diff --git a/README-task-master.md b/README-task-master.md index 7719cdcd..1cce8a3b 100644 --- a/README-task-master.md +++ b/README-task-master.md @@ -323,8 +323,11 @@ Here's a comprehensive reference of all available commands: # Parse a PRD file and generate tasks task-master parse-prd -# Limit the number of tasks generated -task-master parse-prd --num-tasks=10 +# Limit the number of tasks generated (default is 10) +task-master parse-prd --num-tasks=5 + +# Allow task master to determine the number of tasks based on complexity +task-master parse-prd --num-tasks=0 ``` ### List Tasks @@ -397,6 +400,9 @@ When marking a task as "done", all of its subtasks will automatically be marked # Expand a specific task with subtasks task-master expand --id= --num= +# Expand a task with a dynamic number of subtasks (ignoring complexity report) +task-master expand --id= --num=0 + # Expand with additional context task-master expand --id= --prompt="" diff --git a/assets/config.json b/assets/config.json index d015eb4c..8ec52f58 100644 --- a/assets/config.json +++ b/assets/config.json @@ -3,7 +3,7 @@ "main": { "provider": "anthropic", "modelId": "claude-3-7-sonnet-20250219", - "maxTokens": 120000, + "maxTokens": 100000, "temperature": 0.2 }, "research": { @@ -14,9 +14,9 @@ }, "fallback": { "provider": "anthropic", - "modelId": "claude-3-5-sonnet-20240620", + "modelId": "claude-3-7-sonnet-20250219", "maxTokens": 8192, - "temperature": 0.1 + "temperature": 0.2 } }, "global": { @@ -28,6 +28,7 @@ "defaultTag": "master", "ollamaBaseURL": "http://localhost:11434/api", "azureOpenaiBaseURL": "https://your-endpoint.openai.azure.com/", - "bedrockBaseURL": "https://bedrock.us-east-1.amazonaws.com" + "bedrockBaseURL": "https://bedrock.us-east-1.amazonaws.com", + "responseLanguage": "English" } } diff --git a/assets/rules/dev_workflow.mdc b/assets/rules/dev_workflow.mdc index ae6ceeee..84dd906f 100644 --- a/assets/rules/dev_workflow.mdc +++ b/assets/rules/dev_workflow.mdc @@ -153,7 +153,7 @@ When users initialize Taskmaster on existing projects: 4. **Tag-Based Organization**: Parse PRDs into appropriate tags (`refactor-api`, `feature-dashboard`, `tech-debt`, etc.) 5. **Master List Curation**: Keep only the most valuable initiatives in master -The parse-prd's `--append` flag enables the user to parse multple PRDs within tags or across tags. PRDs should be focused and the number of tasks they are parsed into should be strategically chosen relative to the PRD's complexity and level of detail. +The parse-prd's `--append` flag enables the user to parse multiple PRDs within tags or across tags. PRDs should be focused and the number of tasks they are parsed into should be strategically chosen relative to the PRD's complexity and level of detail. ### Workflow Transition Examples diff --git a/assets/rules/taskmaster.mdc b/assets/rules/taskmaster.mdc index b69aa9b0..892d7274 100644 --- a/assets/rules/taskmaster.mdc +++ b/assets/rules/taskmaster.mdc @@ -271,7 +271,7 @@ This document provides a detailed reference for interacting with Taskmaster, cov * **CLI Command:** `task-master clear-subtasks [options]` * **Description:** `Remove all subtasks from one or more specified Taskmaster parent tasks.` * **Key Parameters/Options:** - * `id`: `The ID(s) of the Taskmaster parent task(s) whose subtasks you want to remove, e.g., '15' or '16,18'. Required unless using `all`.) (CLI: `-i, --id `) + * `id`: `The ID(s) of the Taskmaster parent task(s) whose subtasks you want to remove, e.g., '15' or '16,18'. Required unless using 'all'.` (CLI: `-i, --id `) * `all`: `Tell Taskmaster to remove subtasks from all parent tasks.` (CLI: `--all`) * `tag`: `Specify which tag context to operate on. Defaults to the current active tag.` (CLI: `--tag `) * `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file `) diff --git a/docs/command-reference.md b/docs/command-reference.md index d562a645..d7935447 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -8,8 +8,11 @@ Here's a comprehensive reference of all available commands: # Parse a PRD file and generate tasks task-master parse-prd -# Limit the number of tasks generated -task-master parse-prd --num-tasks=10 +# Limit the number of tasks generated (default is 10) +task-master parse-prd --num-tasks=5 + +# Allow task master to determine the number of tasks based on complexity +task-master parse-prd --num-tasks=0 ``` ## List Tasks @@ -128,6 +131,9 @@ When marking a task as "done", all of its subtasks will automatically be marked # Expand a specific task with subtasks task-master expand --id= --num= +# Expand a task with a dynamic number of subtasks (ignoring complexity report) +task-master expand --id= --num=0 + # Expand with additional context task-master expand --id= --prompt="" diff --git a/docs/configuration.md b/docs/configuration.md index 4f2b152f..9be224c5 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -36,6 +36,7 @@ Taskmaster uses two primary methods for configuration: "global": { "logLevel": "info", "debug": false, + "defaultNumTasks": 10, "defaultSubtasks": 5, "defaultPriority": "medium", "defaultTag": "master", @@ -43,7 +44,8 @@ Taskmaster uses two primary methods for configuration: "ollamaBaseURL": "http://localhost:11434/api", "azureBaseURL": "https://your-endpoint.azure.com/openai/deployments", "vertexProjectId": "your-gcp-project-id", - "vertexLocation": "us-central1" + "vertexLocation": "us-central1", + "responseLanguage": "English" } } ``` diff --git a/docs/examples/claude-code-usage.md b/docs/examples/claude-code-usage.md index f8e6c69c..92349b9a 100644 --- a/docs/examples/claude-code-usage.md +++ b/docs/examples/claude-code-usage.md @@ -64,100 +64,81 @@ task-master set-status --id=task-001 --status=in-progress ```bash npm install @anthropic-ai/claude-code ``` -3. No API key is required in your environment variables or MCP configuration +3. Run Claude Code for the first time and authenticate with your Anthropic account: + ```bash + claude + ``` +4. No API key is required in your environment variables or MCP configuration ## Advanced Settings -The Claude Code SDK supports additional settings that provide fine-grained control over Claude's behavior. While these settings are implemented in the underlying SDK (`src/ai-providers/custom-sdk/claude-code/`), they are not currently exposed through Task Master's standard API due to architectural constraints. +The Claude Code SDK supports additional settings that provide fine-grained control over Claude's behavior. These settings are implemented in the underlying SDK (`src/ai-providers/custom-sdk/claude-code/`), and can be managed through Task Master's configuration file. -### Supported Settings +### Advanced Settings Usage + +To update settings for Claude Code, update your `.taskmaster/config.json`: + +The Claude Code settings can be specified globally in the `claudeCode` section of the config, or on a per-command basis in the `commandSpecific` section: ```javascript -const settings = { - // Maximum conversation turns Claude can make in a single request - maxTurns: 5, - - // Custom system prompt to override Claude Code's default behavior - customSystemPrompt: "You are a helpful assistant focused on code quality", - - // Permission mode for file system operations - permissionMode: 'default', // Options: 'default', 'restricted', 'permissive' - - // Explicitly allow only certain tools - allowedTools: ['Read', 'LS'], // Claude can only read files and list directories - - // Explicitly disallow certain tools - disallowedTools: ['Write', 'Edit'], // Prevent Claude from modifying files - - // MCP servers for additional tool integrations - mcpServers: [] -}; -``` +{ + // "models" and "global" config... -### Current Limitations + "claudeCode": { + // Maximum conversation turns Claude can make in a single request + "maxTurns": 5, + + // Custom system prompt to override Claude Code's default behavior + "customSystemPrompt": "You are a helpful assistant focused on code quality", -Task Master uses a standardized `BaseAIProvider` interface that only passes through common parameters (modelId, messages, maxTokens, temperature) to maintain consistency across all providers. The Claude Code advanced settings are implemented in the SDK but not accessible through Task Master's high-level commands. + // Append additional content to the system prompt + "appendSystemPrompt": "Always follow coding best practices", + + // Permission mode for file system operations + "permissionMode": "default", // Options: "default", "acceptEdits", "plan", "bypassPermissions" + + // Explicitly allow only certain tools + "allowedTools": ["Read", "LS"], // Claude can only read files and list directories + + // Explicitly disallow certain tools + "disallowedTools": ["Write", "Edit"], // Prevent Claude from modifying files + + // MCP servers for additional tool integrations + "mcpServers": { + "mcp-server-name": { + "command": "npx", + "args": ["-y", "mcp-serve"], + "env": { + // ... + } + } + } + }, -### Future Integration Options - -For developers who need to use these advanced settings, there are three potential approaches: - -#### Option 1: Extend BaseAIProvider -Modify the core Task Master architecture to support provider-specific settings: - -```javascript -// In BaseAIProvider -const result = await generateText({ - model: client(params.modelId), - messages: params.messages, - maxTokens: params.maxTokens, - temperature: params.temperature, - ...params.providerSettings // New: pass through provider-specific settings -}); -``` - -#### Option 2: Override Methods in ClaudeCodeProvider -Create custom implementations that extract and use Claude-specific settings: - -```javascript -// In ClaudeCodeProvider -async generateText(params) { - const { maxTurns, allowedTools, disallowedTools, ...baseParams } = params; - - const client = this.getClient({ - ...baseParams, - settings: { maxTurns, allowedTools, disallowedTools } - }); - - // Continue with generation... + // Command-specific settings override global settings + "commandSpecific": { + "parse-prd": { + // Settings specific to the 'parse-prd' command + "maxTurns": 10, + "customSystemPrompt": "You are a task breakdown specialist" + }, + "analyze-complexity": { + // Settings specific to the 'analyze-complexity' command + "maxTurns": 3, + "appendSystemPrompt": "Focus on identifying bottlenecks" + } + } } ``` -#### Option 3: Direct SDK Usage -For immediate access to advanced features, developers can use the Claude Code SDK directly: - -```javascript -import { createClaudeCode } from 'task-master-ai/ai-providers/custom-sdk/claude-code'; - -const claude = createClaudeCode({ - defaultSettings: { - maxTurns: 5, - allowedTools: ['Read', 'LS'], - disallowedTools: ['Write', 'Edit'] - } -}); - -const model = claude('sonnet'); -const result = await generateText({ - model, - messages: [{ role: 'user', content: 'Analyze this code...' }] -}); -``` +- For a full list of Cluaude Code settings, see the [Claude Code Settings documentation](https://docs.anthropic.com/en/docs/claude-code/settings). +- For a full list of AI powered command names, see this file: `src/constants/commands.js` ### Why These Settings Matter - **maxTurns**: Useful for complex refactoring tasks that require multiple iterations - **customSystemPrompt**: Allows specializing Claude for specific domains or coding standards +- **appendSystemPrompt**: Useful for enforcing coding standards or providing additional context - **permissionMode**: Critical for security in production environments - **allowedTools/disallowedTools**: Enable read-only analysis modes or restrict access to sensitive operations - **mcpServers**: Future extensibility for custom tool integrations diff --git a/docs/models.md b/docs/models.md index dd8eae91..799a8d1c 100644 --- a/docs/models.md +++ b/docs/models.md @@ -1,10 +1,17 @@ -# Available Models as of June 21, 2025 +# Available Models as of July 2, 2025 ## Main Models | Provider | Model Name | SWE Score | Input Cost | Output Cost | | ----------- | ---------------------------------------------- | --------- | ---------- | ----------- | +| bedrock | us.anthropic.claude-3-haiku-20240307-v1:0 | 0.4 | 0.25 | 1.25 | +| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 | +| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 | +| bedrock | us.anthropic.claude-3-5-sonnet-20241022-v2:0 | 0.49 | 3 | 15 | | bedrock | us.anthropic.claude-3-7-sonnet-20250219-v1:0 | 0.623 | 3 | 15 | +| bedrock | us.anthropic.claude-3-5-haiku-20241022-v1:0 | 0.4 | 0.8 | 4 | +| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 | +| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 | | anthropic | claude-sonnet-4-20250514 | 0.727 | 3 | 15 | | anthropic | claude-opus-4-20250514 | 0.725 | 15 | 75 | | anthropic | claude-3-7-sonnet-20250219 | 0.623 | 3 | 15 | @@ -67,29 +74,46 @@ | openrouter | thudm/glm-4-32b:free | — | 0 | 0 | | claude-code | opus | 0.725 | 0 | 0 | | claude-code | sonnet | 0.727 | 0 | 0 | +| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 | +| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 | ## Research Models -| Provider | Model Name | SWE Score | Input Cost | Output Cost | -| ----------- | -------------------------- | --------- | ---------- | ----------- | -| bedrock | us.deepseek.r1-v1:0 | — | 1.35 | 5.4 | -| openai | gpt-4o-search-preview | 0.33 | 2.5 | 10 | -| openai | gpt-4o-mini-search-preview | 0.3 | 0.15 | 0.6 | -| perplexity | sonar-pro | — | 3 | 15 | -| perplexity | sonar | — | 1 | 1 | -| perplexity | deep-research | 0.211 | 2 | 8 | -| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 | -| perplexity | sonar-reasoning | 0.211 | 1 | 5 | -| xai | grok-3 | — | 3 | 15 | -| xai | grok-3-fast | — | 5 | 25 | -| claude-code | opus | 0.725 | 0 | 0 | -| claude-code | sonnet | 0.727 | 0 | 0 | +| Provider | Model Name | SWE Score | Input Cost | Output Cost | +| ----------- | -------------------------------------------- | --------- | ---------- | ----------- | +| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 | +| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 | +| bedrock | us.anthropic.claude-3-5-sonnet-20241022-v2:0 | 0.49 | 3 | 15 | +| bedrock | us.anthropic.claude-3-7-sonnet-20250219-v1:0 | 0.623 | 3 | 15 | +| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 | +| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 | +| bedrock | us.deepseek.r1-v1:0 | — | 1.35 | 5.4 | +| openai | gpt-4o-search-preview | 0.33 | 2.5 | 10 | +| openai | gpt-4o-mini-search-preview | 0.3 | 0.15 | 0.6 | +| perplexity | sonar-pro | — | 3 | 15 | +| perplexity | sonar | — | 1 | 1 | +| perplexity | deep-research | 0.211 | 2 | 8 | +| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 | +| perplexity | sonar-reasoning | 0.211 | 1 | 5 | +| xai | grok-3 | — | 3 | 15 | +| xai | grok-3-fast | — | 5 | 25 | +| claude-code | opus | 0.725 | 0 | 0 | +| claude-code | sonnet | 0.727 | 0 | 0 | +| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 | +| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 | ## Fallback Models | Provider | Model Name | SWE Score | Input Cost | Output Cost | | ----------- | ---------------------------------------------- | --------- | ---------- | ----------- | +| bedrock | us.anthropic.claude-3-haiku-20240307-v1:0 | 0.4 | 0.25 | 1.25 | +| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 | +| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 | +| bedrock | us.anthropic.claude-3-5-sonnet-20241022-v2:0 | 0.49 | 3 | 15 | | bedrock | us.anthropic.claude-3-7-sonnet-20250219-v1:0 | 0.623 | 3 | 15 | +| bedrock | us.anthropic.claude-3-5-haiku-20241022-v1:0 | 0.4 | 0.8 | 4 | +| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 | +| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 | | anthropic | claude-sonnet-4-20250514 | 0.727 | 3 | 15 | | anthropic | claude-opus-4-20250514 | 0.725 | 15 | 75 | | anthropic | claude-3-7-sonnet-20250219 | 0.623 | 3 | 15 | @@ -141,3 +165,5 @@ | openrouter | thudm/glm-4-32b:free | — | 0 | 0 | | claude-code | opus | 0.725 | 0 | 0 | | claude-code | sonnet | 0.727 | 0 | 0 | +| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 | +| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 | diff --git a/docs/providers/gemini-cli.md b/docs/providers/gemini-cli.md new file mode 100644 index 00000000..79f290a4 --- /dev/null +++ b/docs/providers/gemini-cli.md @@ -0,0 +1,169 @@ +# Gemini CLI Provider + +The Gemini CLI provider allows you to use Google's Gemini models through the Gemini CLI tool, leveraging your existing Gemini subscription and OAuth authentication. + +## Why Use Gemini CLI? + +The primary benefit of using the `gemini-cli` provider is to leverage your existing Gemini Pro subscription or OAuth authentication configured through the Gemini CLI. This is ideal for users who: + +- Have an active Gemini subscription +- Want to use OAuth authentication instead of managing API keys +- Have already configured authentication via `gemini auth login` + +## Installation + +The provider is already included in Task Master. However, you need to install the Gemini CLI tool: + +```bash +# Install gemini CLI globally +npm install -g @google/gemini-cli +``` + +## Authentication + +### Primary Method: CLI Authentication (Recommended) + +The Gemini CLI provider is designed to use your pre-configured OAuth authentication: + +```bash +# Authenticate with your Google account +gemini auth login +``` + +This will open a browser window for OAuth authentication. Once authenticated, Task Master will automatically use these credentials when you select the `gemini-cli` provider. + +### Alternative Method: API Key + +While the primary use case is OAuth authentication, you can also use an API key if needed: + +```bash +export GEMINI_API_KEY="your-gemini-api-key" +``` + +**Note:** If you want to use API keys, consider using the standard `google` provider instead, as `gemini-cli` is specifically designed for OAuth/subscription users. + +## Configuration + +Configure `gemini-cli` as a provider using the Task Master models command: + +```bash +# Set gemini-cli as your main provider with gemini-2.5-pro +task-master models --set-main gemini-2.5-pro --gemini-cli + +# Or use the faster gemini-2.5-flash model +task-master models --set-main gemini-2.5-flash --gemini-cli +``` + +You can also manually edit your `.taskmaster/config/providers.json`: + +```json +{ + "main": { + "provider": "gemini-cli", + "model": "gemini-2.5-flash" + } +} +``` + +### Available Models + +The gemini-cli provider supports only two models: +- `gemini-2.5-pro` - High performance model (1M token context window, 65,536 max output tokens) +- `gemini-2.5-flash` - Fast, efficient model (1M token context window, 65,536 max output tokens) + +## Usage Examples + +### Basic Usage + +Once authenticated with `gemini auth login` and configured, simply use Task Master as normal: + +```bash +# The provider will automatically use your OAuth credentials +task-master new "Create a hello world function" +``` + +### With Specific Parameters + +Configure model parameters in your providers.json: + +```json +{ + "main": { + "provider": "gemini-cli", + "model": "gemini-2.5-pro", + "parameters": { + "maxTokens": 65536, + "temperature": 0.7 + } + } +} +``` + +### As Fallback Provider + +Use gemini-cli as a fallback when your primary provider is unavailable: + +```json +{ + "main": { + "provider": "anthropic", + "model": "claude-3-5-sonnet-latest" + }, + "fallback": { + "provider": "gemini-cli", + "model": "gemini-2.5-flash" + } +} +``` + +## Troubleshooting + +### "Authentication failed" Error + +If you get an authentication error: + +1. **Primary solution**: Run `gemini auth login` to authenticate with your Google account +2. **Check authentication status**: Run `gemini auth status` to verify you're logged in +3. **If using API key** (not recommended): Ensure `GEMINI_API_KEY` is set correctly + +### "Model not found" Error + +The gemini-cli provider only supports two models: +- `gemini-2.5-pro` +- `gemini-2.5-flash` + +If you need other Gemini models, use the standard `google` provider with an API key instead. + +### Gemini CLI Not Found + +If you get a "gemini: command not found" error: + +```bash +# Install the Gemini CLI globally +npm install -g @google/gemini-cli + +# Verify installation +gemini --version +``` + +### Custom Endpoints + +Custom endpoints can be configured if needed: + +```json +{ + "main": { + "provider": "gemini-cli", + "model": "gemini-2.5-pro", + "baseURL": "https://custom-endpoint.example.com" + } +} +``` + +## Important Notes + +- **OAuth vs API Key**: This provider is specifically designed for users who want to use OAuth authentication via `gemini auth login`. If you prefer using API keys, consider using the standard `google` provider instead. +- **Limited Model Support**: Only `gemini-2.5-pro` and `gemini-2.5-flash` are available through gemini-cli. +- **Subscription Benefits**: Using OAuth authentication allows you to leverage any subscription benefits associated with your Google account. +- The provider uses the `ai-sdk-provider-gemini-cli` npm package internally. +- Supports all standard Task Master features: text generation, streaming, and structured object generation. \ No newline at end of file diff --git a/mcp-server/src/core/direct-functions/add-subtask.js b/mcp-server/src/core/direct-functions/add-subtask.js index 9c52d88f..1790bbdd 100644 --- a/mcp-server/src/core/direct-functions/add-subtask.js +++ b/mcp-server/src/core/direct-functions/add-subtask.js @@ -20,6 +20,8 @@ import { * @param {string} [args.status] - Status for new subtask (default: 'pending') * @param {string} [args.dependencies] - Comma-separated list of dependency IDs * @param {boolean} [args.skipGenerate] - Skip regenerating task files + * @param {string} [args.projectRoot] - Project root directory + * @param {string} [args.tag] - Tag for the task * @param {Object} log - Logger object * @returns {Promise<{success: boolean, data?: Object, error?: string}>} */ @@ -34,7 +36,9 @@ export async function addSubtaskDirect(args, log) { details, status, dependencies: dependenciesStr, - skipGenerate + skipGenerate, + projectRoot, + tag } = args; try { log.info(`Adding subtask with args: ${JSON.stringify(args)}`); @@ -96,6 +100,8 @@ export async function addSubtaskDirect(args, log) { // Enable silent mode to prevent console logs from interfering with JSON response enableSilentMode(); + const context = { projectRoot, tag }; + // Case 1: Convert existing task to subtask if (existingTaskId) { log.info(`Converting task ${existingTaskId} to a subtask of ${parentId}`); @@ -104,7 +110,8 @@ export async function addSubtaskDirect(args, log) { parentId, existingTaskId, null, - generateFiles + generateFiles, + context ); // Restore normal logging @@ -135,7 +142,8 @@ export async function addSubtaskDirect(args, log) { parentId, null, newSubtaskData, - generateFiles + generateFiles, + context ); // Restore normal logging diff --git a/mcp-server/src/core/direct-functions/expand-task.js b/mcp-server/src/core/direct-functions/expand-task.js index f0513bec..d231a95c 100644 --- a/mcp-server/src/core/direct-functions/expand-task.js +++ b/mcp-server/src/core/direct-functions/expand-task.js @@ -171,8 +171,8 @@ export async function expandTaskDirect(args, log, context = {}) { task.subtasks = []; } - // Save tasks.json with potentially empty subtasks array - writeJSON(tasksPath, data); + // Save tasks.json with potentially empty subtasks array and proper context + writeJSON(tasksPath, data, projectRoot, tag); // Create logger wrapper using the utility const mcpLog = createLogWrapper(log); diff --git a/mcp-server/src/core/direct-functions/fix-dependencies.js b/mcp-server/src/core/direct-functions/fix-dependencies.js index 65dd407c..7bfceddf 100644 --- a/mcp-server/src/core/direct-functions/fix-dependencies.js +++ b/mcp-server/src/core/direct-functions/fix-dependencies.js @@ -13,12 +13,14 @@ import fs from 'fs'; * Fix invalid dependencies in tasks.json automatically * @param {Object} args - Function arguments * @param {string} args.tasksJsonPath - Explicit path to the tasks.json file. + * @param {string} args.projectRoot - Project root directory + * @param {string} args.tag - Tag for the project * @param {Object} log - Logger object * @returns {Promise<{success: boolean, data?: Object, error?: {code: string, message: string}}>} */ export async function fixDependenciesDirect(args, log) { // Destructure expected args - const { tasksJsonPath } = args; + const { tasksJsonPath, projectRoot, tag } = args; try { log.info(`Fixing invalid dependencies in tasks: ${tasksJsonPath}`); @@ -51,8 +53,10 @@ export async function fixDependenciesDirect(args, log) { // Enable silent mode to prevent console logs from interfering with JSON response enableSilentMode(); - // Call the original command function using the provided path - await fixDependenciesCommand(tasksPath); + // Call the original command function using the provided path and proper context + await fixDependenciesCommand(tasksPath, { + context: { projectRoot, tag } + }); // Restore normal logging disableSilentMode(); @@ -61,7 +65,8 @@ export async function fixDependenciesDirect(args, log) { success: true, data: { message: 'Dependencies fixed successfully', - tasksPath + tasksPath, + tag: tag || 'master' } }; } catch (error) { diff --git a/mcp-server/src/core/direct-functions/initialize-project.js b/mcp-server/src/core/direct-functions/initialize-project.js index f6a2a8c2..d9e0cff9 100644 --- a/mcp-server/src/core/direct-functions/initialize-project.js +++ b/mcp-server/src/core/direct-functions/initialize-project.js @@ -72,15 +72,16 @@ export async function initializeProjectDirect(args, log, context = {}) { yes: true // Force yes mode }; - // Handle rules option just like CLI + // Handle rules option with MCP-specific defaults if (Array.isArray(args.rules) && args.rules.length > 0) { options.rules = args.rules; + options.rulesExplicitlyProvided = true; log.info(`Including rules: ${args.rules.join(', ')}`); } else { - options.rules = RULE_PROFILES; - log.info( - `No rule profiles specified, defaulting to: ${RULE_PROFILES.join(', ')}` - ); + // For MCP initialization, default to Cursor profile only + options.rules = ['cursor']; + options.rulesExplicitlyProvided = true; + log.info(`No rule profiles specified, defaulting to: Cursor`); } log.info(`Initializing project with options: ${JSON.stringify(options)}`); diff --git a/mcp-server/src/core/direct-functions/parse-prd.js b/mcp-server/src/core/direct-functions/parse-prd.js index ac1642e2..7c269547 100644 --- a/mcp-server/src/core/direct-functions/parse-prd.js +++ b/mcp-server/src/core/direct-functions/parse-prd.js @@ -109,7 +109,7 @@ export async function parsePRDDirect(args, log, context = {}) { if (numTasksArg) { numTasks = typeof numTasksArg === 'string' ? parseInt(numTasksArg, 10) : numTasksArg; - if (Number.isNaN(numTasks) || numTasks <= 0) { + if (Number.isNaN(numTasks) || numTasks < 0) { // Ensure positive number numTasks = getDefaultNumTasks(projectRoot); // Fallback to default if parsing fails or invalid logWrapper.warn( diff --git a/mcp-server/src/core/direct-functions/remove-task.js b/mcp-server/src/core/direct-functions/remove-task.js index 34200f41..33842249 100644 --- a/mcp-server/src/core/direct-functions/remove-task.js +++ b/mcp-server/src/core/direct-functions/remove-task.js @@ -20,12 +20,13 @@ import { * @param {Object} args - Command arguments * @param {string} args.tasksJsonPath - Explicit path to the tasks.json file. * @param {string} args.id - The ID(s) of the task(s) or subtask(s) to remove (comma-separated for multiple). + * @param {string} [args.tag] - Tag context to operate on (defaults to current active tag). * @param {Object} log - Logger object * @returns {Promise} - Remove task result { success: boolean, data?: any, error?: { code: string, message: string } } */ export async function removeTaskDirect(args, log, context = {}) { // Destructure expected args - const { tasksJsonPath, id, projectRoot } = args; + const { tasksJsonPath, id, projectRoot, tag } = args; const { session } = context; try { // Check if tasksJsonPath was provided @@ -56,17 +57,17 @@ export async function removeTaskDirect(args, log, context = {}) { const taskIdArray = id.split(',').map((taskId) => taskId.trim()); log.info( - `Removing ${taskIdArray.length} task(s) with ID(s): ${taskIdArray.join(', ')} from ${tasksJsonPath}` + `Removing ${taskIdArray.length} task(s) with ID(s): ${taskIdArray.join(', ')} from ${tasksJsonPath}${tag ? ` in tag '${tag}'` : ''}` ); // Validate all task IDs exist before proceeding - const data = readJSON(tasksJsonPath, projectRoot); + const data = readJSON(tasksJsonPath, projectRoot, tag); if (!data || !data.tasks) { return { success: false, error: { code: 'INVALID_TASKS_FILE', - message: `No valid tasks found in ${tasksJsonPath}` + message: `No valid tasks found in ${tasksJsonPath}${tag ? ` for tag '${tag}'` : ''}` } }; } @@ -80,71 +81,49 @@ export async function removeTaskDirect(args, log, context = {}) { success: false, error: { code: 'INVALID_TASK_ID', - message: `The following tasks were not found: ${invalidTasks.join(', ')}` + message: `The following tasks were not found${tag ? ` in tag '${tag}'` : ''}: ${invalidTasks.join(', ')}` } }; } - // Remove tasks one by one - const results = []; - // Enable silent mode to prevent console logs from interfering with JSON response enableSilentMode(); try { - for (const taskId of taskIdArray) { - try { - const result = await removeTask(tasksJsonPath, taskId); - results.push({ - taskId, - success: true, - message: result.message, - removedTask: result.removedTask - }); - log.info(`Successfully removed task: ${taskId}`); - } catch (error) { - results.push({ - taskId, - success: false, - error: error.message - }); - log.error(`Error removing task ${taskId}: ${error.message}`); - } + // Call removeTask with proper context including tag + const result = await removeTask(tasksJsonPath, id, { + projectRoot, + tag + }); + + if (!result.success) { + return { + success: false, + error: { + code: 'REMOVE_TASK_ERROR', + message: result.error || 'Failed to remove tasks' + } + }; } + + log.info(`Successfully removed ${result.removedTasks.length} task(s)`); + + return { + success: true, + data: { + totalTasks: taskIdArray.length, + successful: result.removedTasks.length, + failed: taskIdArray.length - result.removedTasks.length, + removedTasks: result.removedTasks, + message: result.message, + tasksPath: tasksJsonPath, + tag: data.tag || tag || 'master' + } + }; } finally { // Restore normal logging disableSilentMode(); } - - // Check if all tasks were successfully removed - const successfulRemovals = results.filter((r) => r.success); - const failedRemovals = results.filter((r) => !r.success); - - if (successfulRemovals.length === 0) { - // All removals failed - return { - success: false, - error: { - code: 'REMOVE_TASK_ERROR', - message: 'Failed to remove any tasks', - details: failedRemovals - .map((r) => `${r.taskId}: ${r.error}`) - .join('; ') - } - }; - } - - // At least some tasks were removed successfully - return { - success: true, - data: { - totalTasks: taskIdArray.length, - successful: successfulRemovals.length, - failed: failedRemovals.length, - results: results, - tasksPath: tasksJsonPath - } - }; } catch (error) { // Ensure silent mode is disabled even if an outer error occurs disableSilentMode(); diff --git a/mcp-server/src/core/direct-functions/response-language.js b/mcp-server/src/core/direct-functions/response-language.js new file mode 100644 index 00000000..e39bda74 --- /dev/null +++ b/mcp-server/src/core/direct-functions/response-language.js @@ -0,0 +1,40 @@ +/** + * response-language.js + * Direct function for managing response language via MCP + */ + +import { setResponseLanguage } from '../../../../scripts/modules/task-manager.js'; +import { + enableSilentMode, + disableSilentMode +} from '../../../../scripts/modules/utils.js'; +import { createLogWrapper } from '../../tools/utils.js'; + +export async function responseLanguageDirect(args, log, context = {}) { + const { projectRoot, language } = args; + const mcpLog = createLogWrapper(log); + + log.info( + `Executing response-language_direct with args: ${JSON.stringify(args)}` + ); + log.info(`Using project root: ${projectRoot}`); + + try { + enableSilentMode(); + return setResponseLanguage(language, { + mcpLog, + projectRoot + }); + } catch (error) { + return { + success: false, + error: { + code: 'DIRECT_FUNCTION_ERROR', + message: error.message, + details: error.stack + } + }; + } finally { + disableSilentMode(); + } +} diff --git a/mcp-server/src/core/direct-functions/set-task-status.js b/mcp-server/src/core/direct-functions/set-task-status.js index da0eeb41..aacd94fc 100644 --- a/mcp-server/src/core/direct-functions/set-task-status.js +++ b/mcp-server/src/core/direct-functions/set-task-status.js @@ -20,7 +20,8 @@ import { nextTaskDirect } from './next-task.js'; */ export async function setTaskStatusDirect(args, log, context = {}) { // Destructure expected args, including the resolved tasksJsonPath and projectRoot - const { tasksJsonPath, id, status, complexityReportPath, projectRoot } = args; + const { tasksJsonPath, id, status, complexityReportPath, projectRoot, tag } = + args; const { session } = context; try { log.info(`Setting task status with args: ${JSON.stringify(args)}`); @@ -69,11 +70,17 @@ export async function setTaskStatusDirect(args, log, context = {}) { enableSilentMode(); // Enable silent mode before calling core function try { // Call the core function - await setTaskStatus(tasksPath, taskId, newStatus, { - mcpLog: log, - projectRoot, - session - }); + await setTaskStatus( + tasksPath, + taskId, + newStatus, + { + mcpLog: log, + projectRoot, + session + }, + tag + ); log.info(`Successfully set task ${taskId} status to ${newStatus}`); diff --git a/mcp-server/src/core/direct-functions/update-tasks.js b/mcp-server/src/core/direct-functions/update-tasks.js index 1b33eca2..36d1ef4e 100644 --- a/mcp-server/src/core/direct-functions/update-tasks.js +++ b/mcp-server/src/core/direct-functions/update-tasks.js @@ -21,7 +21,7 @@ import { */ export async function updateTasksDirect(args, log, context = {}) { const { session } = context; - const { from, prompt, research, tasksJsonPath, projectRoot } = args; + const { from, prompt, research, tasksJsonPath, projectRoot, tag } = args; // Create the standard logger wrapper const logWrapper = createLogWrapper(log); @@ -75,7 +75,8 @@ export async function updateTasksDirect(args, log, context = {}) { { session, mcpLog: logWrapper, - projectRoot + projectRoot, + tag }, 'json' ); diff --git a/mcp-server/src/tools/add-subtask.js b/mcp-server/src/tools/add-subtask.js index 6e6fd377..8d1fda44 100644 --- a/mcp-server/src/tools/add-subtask.js +++ b/mcp-server/src/tools/add-subtask.js @@ -52,6 +52,7 @@ export function registerAddSubtaskTool(server) { .describe( 'Absolute path to the tasks file (default: tasks/tasks.json)' ), + tag: z.string().optional().describe('Tag context to operate on'), skipGenerate: z .boolean() .optional() @@ -89,7 +90,8 @@ export function registerAddSubtaskTool(server) { status: args.status, dependencies: args.dependencies, skipGenerate: args.skipGenerate, - projectRoot: args.projectRoot + projectRoot: args.projectRoot, + tag: args.tag }, log, { session } diff --git a/mcp-server/src/tools/fix-dependencies.js b/mcp-server/src/tools/fix-dependencies.js index 34ffcdf5..c46d18bc 100644 --- a/mcp-server/src/tools/fix-dependencies.js +++ b/mcp-server/src/tools/fix-dependencies.js @@ -24,7 +24,8 @@ export function registerFixDependenciesTool(server) { file: z.string().optional().describe('Absolute path to the tasks file'), projectRoot: z .string() - .describe('The directory of the project. Must be an absolute path.') + .describe('The directory of the project. Must be an absolute path.'), + tag: z.string().optional().describe('Tag context to operate on') }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { @@ -46,7 +47,9 @@ export function registerFixDependenciesTool(server) { const result = await fixDependenciesDirect( { - tasksJsonPath: tasksJsonPath + tasksJsonPath: tasksJsonPath, + projectRoot: args.projectRoot, + tag: args.tag }, log ); diff --git a/mcp-server/src/tools/index.js b/mcp-server/src/tools/index.js index a4aaaecc..32144619 100644 --- a/mcp-server/src/tools/index.js +++ b/mcp-server/src/tools/index.js @@ -29,6 +29,7 @@ import { registerRemoveTaskTool } from './remove-task.js'; import { registerInitializeProjectTool } from './initialize-project.js'; import { registerModelsTool } from './models.js'; import { registerMoveTaskTool } from './move-task.js'; +import { registerResponseLanguageTool } from './response-language.js'; import { registerAddTagTool } from './add-tag.js'; import { registerDeleteTagTool } from './delete-tag.js'; import { registerListTagsTool } from './list-tags.js'; @@ -83,6 +84,7 @@ export function registerTaskMasterTools(server) { registerRemoveDependencyTool(server); registerValidateDependenciesTool(server); registerFixDependenciesTool(server); + registerResponseLanguageTool(server); // Group 7: Tag Management registerListTagsTool(server); diff --git a/mcp-server/src/tools/initialize-project.js b/mcp-server/src/tools/initialize-project.js index 30ddf1a7..6bf380d6 100644 --- a/mcp-server/src/tools/initialize-project.js +++ b/mcp-server/src/tools/initialize-project.js @@ -51,7 +51,7 @@ export function registerInitializeProjectTool(server) { .array(z.enum(RULE_PROFILES)) .optional() .describe( - `List of rule profiles to include at initialization. If omitted, defaults to all available profiles. Available options: ${RULE_PROFILES.join(', ')}` + `List of rule profiles to include at initialization. If omitted, defaults to Cursor profile only. Available options: ${RULE_PROFILES.join(', ')}` ) }), execute: withNormalizedProjectRoot(async (args, context) => { diff --git a/mcp-server/src/tools/parse-prd.js b/mcp-server/src/tools/parse-prd.js index ec8bafb9..db11f4c0 100644 --- a/mcp-server/src/tools/parse-prd.js +++ b/mcp-server/src/tools/parse-prd.js @@ -43,7 +43,7 @@ export function registerParsePRDTool(server) { .string() .optional() .describe( - 'Approximate number of top-level tasks to generate (default: 10). As the agent, if you have enough information, ensure to enter a number of tasks that would logically scale with project complexity. Avoid entering numbers above 50 due to context window limitations.' + 'Approximate number of top-level tasks to generate (default: 10). As the agent, if you have enough information, ensure to enter a number of tasks that would logically scale with project complexity. Setting to 0 will allow Taskmaster to determine the appropriate number of tasks based on the complexity of the PRD. Avoid entering numbers above 50 due to context window limitations.' ), force: z .boolean() diff --git a/mcp-server/src/tools/remove-task.js b/mcp-server/src/tools/remove-task.js index 81e25f5e..c2b1c60c 100644 --- a/mcp-server/src/tools/remove-task.js +++ b/mcp-server/src/tools/remove-task.js @@ -33,7 +33,13 @@ export function registerRemoveTaskTool(server) { confirm: z .boolean() .optional() - .describe('Whether to skip confirmation prompt (default: false)') + .describe('Whether to skip confirmation prompt (default: false)'), + tag: z + .string() + .optional() + .describe( + 'Specify which tag context to operate on. Defaults to the current active tag.' + ) }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { @@ -59,7 +65,8 @@ export function registerRemoveTaskTool(server) { { tasksJsonPath: tasksJsonPath, id: args.id, - projectRoot: args.projectRoot + projectRoot: args.projectRoot, + tag: args.tag }, log, { session } diff --git a/mcp-server/src/tools/response-language.js b/mcp-server/src/tools/response-language.js new file mode 100644 index 00000000..42a8ee06 --- /dev/null +++ b/mcp-server/src/tools/response-language.js @@ -0,0 +1,46 @@ +import { z } from 'zod'; +import { + createErrorResponse, + handleApiResult, + withNormalizedProjectRoot +} from './utils.js'; +import { responseLanguageDirect } from '../core/direct-functions/response-language.js'; + +export function registerResponseLanguageTool(server) { + server.addTool({ + name: 'response-language', + description: 'Get or set the response language for the project', + parameters: z.object({ + projectRoot: z + .string() + .describe( + 'The root directory for the project. ALWAYS SET THIS TO THE PROJECT ROOT DIRECTORY. IF NOT SET, THE TOOL WILL NOT WORK.' + ), + language: z + .string() + .describe( + 'The new response language to set. like "中文" "English" or "español".' + ) + }), + execute: withNormalizedProjectRoot(async (args, { log, session }) => { + try { + log.info( + `Executing response-language tool with args: ${JSON.stringify(args)}` + ); + + const result = await responseLanguageDirect( + { + ...args, + projectRoot: args.projectRoot + }, + log, + { session } + ); + return handleApiResult(result, log, 'Error setting response language'); + } catch (error) { + log.error(`Error in response-language tool: ${error.message}`); + return createErrorResponse(error.message); + } + }) + }); +} diff --git a/mcp-server/src/tools/set-task-status.js b/mcp-server/src/tools/set-task-status.js index a9cb13a0..ad6edb9b 100644 --- a/mcp-server/src/tools/set-task-status.js +++ b/mcp-server/src/tools/set-task-status.js @@ -47,7 +47,8 @@ export function registerSetTaskStatusTool(server) { ), projectRoot: z .string() - .describe('The directory of the project. Must be an absolute path.') + .describe('The directory of the project. Must be an absolute path.'), + tag: z.string().optional().describe('Optional tag context to operate on') }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { @@ -86,7 +87,8 @@ export function registerSetTaskStatusTool(server) { id: args.id, status: args.status, complexityReportPath, - projectRoot: args.projectRoot + projectRoot: args.projectRoot, + tag: args.tag }, log, { session } diff --git a/mcp-server/src/tools/update.js b/mcp-server/src/tools/update.js index 8d9785ef..475eb338 100644 --- a/mcp-server/src/tools/update.js +++ b/mcp-server/src/tools/update.js @@ -43,11 +43,12 @@ export function registerUpdateTool(server) { .optional() .describe( 'The directory of the project. (Optional, usually from session)' - ) + ), + tag: z.string().optional().describe('Tag context to operate on') }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { const toolName = 'update'; - const { from, prompt, research, file, projectRoot } = args; + const { from, prompt, research, file, projectRoot, tag } = args; try { log.info( @@ -71,7 +72,8 @@ export function registerUpdateTool(server) { from: from, prompt: prompt, research: research, - projectRoot: projectRoot + projectRoot: projectRoot, + tag: tag }, log, { session } diff --git a/package-lock.json b/package-lock.json index 761b7606..94917a68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "task-master-ai", - "version": "0.17.1", + "version": "0.18.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "task-master-ai", - "version": "0.17.1", + "version": "0.18.0", "license": "MIT WITH Commons-Clause", "dependencies": { "@ai-sdk/amazon-bedrock": "^2.2.9", @@ -38,6 +38,7 @@ "gradient-string": "^3.0.0", "helmet": "^8.1.0", "inquirer": "^12.5.0", + "jsonc-parser": "^3.3.1", "jsonwebtoken": "^9.0.2", "lru-cache": "^10.2.0", "ollama-ai-provider": "^1.2.0", @@ -70,13 +71,14 @@ "node": ">=18.0.0" }, "optionalDependencies": { - "@anthropic-ai/claude-code": "^1.0.25" + "@anthropic-ai/claude-code": "^1.0.25", + "ai-sdk-provider-gemini-cli": "^0.0.3" } }, "node_modules/@ai-sdk/amazon-bedrock": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-2.2.9.tgz", - "integrity": "sha512-c4IWCheWLJq7HhRhr0crlB6wqy8KuVj7hsO7pxl7KaYgCiRFkJA3q8Fv9rUJK4XjtOeFxDs6j2z3hVG62jMxDQ==", + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-2.2.11.tgz", + "integrity": "sha512-tZmJbOhihNfkhDnL4sVyscYiMXadXOoZ8QCqU3NVi7kho6czbNal05QZA+EMv1QL87NJAd0FZwcDIy60tor4SQ==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", @@ -92,23 +94,6 @@ "zod": "^3.0.0" } }, - "node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider-utils": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", - "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "1.1.3", - "nanoid": "^3.3.8", - "secure-json-parse": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.23.8" - } - }, "node_modules/@ai-sdk/anthropic": { "version": "1.2.12", "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-1.2.12.tgz", @@ -125,48 +110,15 @@ "zod": "^3.0.0" } }, - "node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider-utils": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", - "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "1.1.3", - "nanoid": "^3.3.8", - "secure-json-parse": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.23.8" - } - }, "node_modules/@ai-sdk/azure": { - "version": "1.3.17", - "resolved": "https://registry.npmjs.org/@ai-sdk/azure/-/azure-1.3.17.tgz", - "integrity": "sha512-uGCQ7q81S3mY1EmH2mrsysc/Qw9czMiNTJDr5fc5ocDnHS89rbiaNUdBbdYpjS471EEa2Rcrx2FTCGiQ0gTPDQ==", + "version": "1.3.23", + "resolved": "https://registry.npmjs.org/@ai-sdk/azure/-/azure-1.3.23.tgz", + "integrity": "sha512-vpsaPtU24RBVk/IMM5UylR/N4RtAuL2NZLWc7LJ3tvMTHu6pI46a7w+1qIwR3F6yO9ehWR8qvfLaBefJNFxaVw==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/openai": "1.3.16", + "@ai-sdk/openai": "1.3.22", "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.0.0" - } - }, - "node_modules/@ai-sdk/azure/node_modules/@ai-sdk/openai": { - "version": "1.3.16", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-1.3.16.tgz", - "integrity": "sha512-pjtiBKt1GgaSKZryTbM3tqgoegJwgAUlp1+X5uN6T+VPnI4FLSymV65tyloWzDlyqZmi9HXnnSRPu76VoL5D5g==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7" + "@ai-sdk/provider-utils": "2.2.8" }, "engines": { "node": ">=18" @@ -176,9 +128,9 @@ } }, "node_modules/@ai-sdk/google": { - "version": "1.2.18", - "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-1.2.18.tgz", - "integrity": "sha512-8B70+i+uB12Ae6Sn6B9Oc6W0W/XorGgc88Nx0pyUrcxFOdytHBaAVhTPqYsO3LLClfjYN8pQ9GMxd5cpGEnUcA==", + "version": "1.2.21", + "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-1.2.21.tgz", + "integrity": "sha512-CbkZ4EYHfxLQzk5dr8Tw/37gug/61EzWelZruKiebEjzAlKSmKQ7625GeLu5w6NibWa5f9cOpEmTxm4kUD8w5Q==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", @@ -192,13 +144,13 @@ } }, "node_modules/@ai-sdk/google-vertex": { - "version": "2.2.23", - "resolved": "https://registry.npmjs.org/@ai-sdk/google-vertex/-/google-vertex-2.2.23.tgz", - "integrity": "sha512-q8rOXqEYBOTcgVW1+QlkYEd+bP1ZWfRYhRs3QzzAL1SP3AQqltuKM7ovO53AFDq5hwlodFMHQ4v9WmXmibgjAg==", + "version": "2.2.26", + "resolved": "https://registry.npmjs.org/@ai-sdk/google-vertex/-/google-vertex-2.2.26.tgz", + "integrity": "sha512-k3qMJBYWZwGlBMIRqDqJKjIENzfHrwC6O8VnmYkwM9BSybxJi3toE1KNe6s1mTVt2DKXkPOy84813FGc/UK3qw==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/anthropic": "1.2.12", - "@ai-sdk/google": "1.2.18", + "@ai-sdk/google": "1.2.21", "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "google-auth-library": "^9.15.0" @@ -210,48 +162,14 @@ "zod": "^3.0.0" } }, - "node_modules/@ai-sdk/google-vertex/node_modules/@ai-sdk/provider-utils": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", - "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "1.1.3", - "nanoid": "^3.3.8", - "secure-json-parse": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.23.8" - } - }, - "node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider-utils": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", - "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "1.1.3", - "nanoid": "^3.3.8", - "secure-json-parse": "^2.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.23.8" - } - }, "node_modules/@ai-sdk/mistral": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@ai-sdk/mistral/-/mistral-1.2.7.tgz", - "integrity": "sha512-MbOMGfnHKcsvjbv4d6OT7Oaz+Wp4jD8yityqC4hASoKoW1s7L52woz25ES8RgAgTRlfbEZ3MOxEzLu58I228bQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/mistral/-/mistral-1.2.8.tgz", + "integrity": "sha512-lv857D9UJqCVxiq2Fcu7mSPTypEHBUqLl1K+lCaP6X/7QAkcaxI36QDONG+tOhGHJOXTsS114u8lrUTaEiGXbg==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7" + "@ai-sdk/provider-utils": "2.2.8" }, "engines": { "node": ">=18" @@ -261,13 +179,13 @@ } }, "node_modules/@ai-sdk/openai": { - "version": "1.3.20", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-1.3.20.tgz", - "integrity": "sha512-/DflUy7ROG9k6n6YTXMBFPbujBKnbGY58f3CwvicLvDar9nDAloVnUWd3LUoOxpSVnX8vtQ7ngxF52SLWO6RwQ==", + "version": "1.3.22", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-1.3.22.tgz", + "integrity": "sha512-QwA+2EkG0QyjVR+7h6FE7iOu2ivNqAVMm9UJZkVxxTk5OIq5fFJDTEI/zICEMuHImTTXR2JjsL6EirJ28Jc4cw==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7" + "@ai-sdk/provider-utils": "2.2.8" }, "engines": { "node": ">=18" @@ -277,13 +195,13 @@ } }, "node_modules/@ai-sdk/openai-compatible": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai-compatible/-/openai-compatible-0.2.13.tgz", - "integrity": "sha512-tB+lL8Z3j0qDod/mvxwjrPhbLUHp/aQW+NvMoJaqeTtP+Vmv5qR800pncGczxn5WN0pllQm+7aIRDnm69XeSbg==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai-compatible/-/openai-compatible-0.2.14.tgz", + "integrity": "sha512-icjObfMCHKSIbywijaoLdZ1nSnuRnWgMEMLgwoxPJgxsUHMx0aVORnsLUid4SPtdhHI3X2masrt6iaEQLvOSFw==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7" + "@ai-sdk/provider-utils": "2.2.8" }, "engines": { "node": ">=18" @@ -293,13 +211,13 @@ } }, "node_modules/@ai-sdk/perplexity": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@ai-sdk/perplexity/-/perplexity-1.1.7.tgz", - "integrity": "sha512-FH2zEADLU/NTuRkQXMbZkUZ0qSsJ5qhufQ+7IsFMuhhKShGt0M8gOZlnkxuolnIjDrOdD3r1r59nZKMsFHuwqw==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@ai-sdk/perplexity/-/perplexity-1.1.9.tgz", + "integrity": "sha512-Ytolh/v2XupXbTvjE18EFBrHLoNMH0Ueji3lfSPhCoRUfkwrgZ2D9jlNxvCNCCRiGJG5kfinSHvzrH5vGDklYA==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7" + "@ai-sdk/provider-utils": "2.2.8" }, "engines": { "node": ">=18" @@ -321,9 +239,9 @@ } }, "node_modules/@ai-sdk/provider-utils": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.7.tgz", - "integrity": "sha512-kM0xS3GWg3aMChh9zfeM+80vEZfXzR3JEUBdycZLtbRZ2TRT8xOj3WodGHPb06sUK5yD7pAXC/P7ctsi2fvUGQ==", + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz", + "integrity": "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", @@ -338,13 +256,13 @@ } }, "node_modules/@ai-sdk/react": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.2.9.tgz", - "integrity": "sha512-/VYm8xifyngaqFDLXACk/1czDRCefNCdALUyp+kIX6DUIYUWTM93ISoZ+qJ8+3E+FiJAKBQz61o8lIIl+vYtzg==", + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.2.12.tgz", + "integrity": "sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider-utils": "2.2.7", - "@ai-sdk/ui-utils": "1.2.8", + "@ai-sdk/provider-utils": "2.2.8", + "@ai-sdk/ui-utils": "1.2.11", "swr": "^2.2.5", "throttleit": "2.1.0" }, @@ -362,13 +280,13 @@ } }, "node_modules/@ai-sdk/ui-utils": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.2.8.tgz", - "integrity": "sha512-nls/IJCY+ks3Uj6G/agNhXqQeLVqhNfoJbuNgCny+nX2veY5ADB91EcZUqVeQ/ionul2SeUswPY6Q/DxteY29Q==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.2.11.tgz", + "integrity": "sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7", + "@ai-sdk/provider-utils": "2.2.8", "zod-to-json-schema": "^3.24.1" }, "engines": { @@ -379,14 +297,14 @@ } }, "node_modules/@ai-sdk/xai": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@ai-sdk/xai/-/xai-1.2.15.tgz", - "integrity": "sha512-18qEYyVHIqTiOMePE00bfx4kJrTHM4dV3D3Rpe+eBISlY80X1FnzZRnRTJo3Q6MOSmW5+ZKVaX9jtryhoFpn0A==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@ai-sdk/xai/-/xai-1.2.16.tgz", + "integrity": "sha512-UOZT8td9PWwMi2dF9a0U44t/Oltmf6QmIJdSvrOcLG4mvpRc1UJn6YJaR0HtXs3YnW6SvY1zRdIDrW4GFpv4NA==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/openai-compatible": "0.2.13", + "@ai-sdk/openai-compatible": "0.2.14", "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7" + "@ai-sdk/provider-utils": "2.2.8" }, "engines": { "node": ">=18" @@ -409,32 +327,6 @@ "node": ">=14.13.1" } }, - "node_modules/@alcalzone/ansi-tokenize/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@alcalzone/ansi-tokenize/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -450,9 +342,9 @@ } }, "node_modules/@anthropic-ai/claude-code": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-1.0.25.tgz", - "integrity": "sha512-5p4FLlFO4TuRf0zV0axiOxiAkUC8eer0lqJi/A/pA46LESv31Alw6xaNYgwQVkP6oSbP5PydK36u7YrB9QSaXQ==", + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-1.0.38.tgz", + "integrity": "sha512-hPZbJCt7O8T872wbCXGiwF210DzMBo/k3EVKB6EZQB10b73ZQIEflAWGTC2ZvBcMp79qAR4F6c82V0+Cc6o0sg==", "hasInstallScript": true, "license": "SEE LICENSE IN README.md", "optional": true, @@ -486,26 +378,6 @@ "node-fetch": "^2.6.7" } }, - "node_modules/@anthropic-ai/sdk/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/@aws-crypto/crc32": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", @@ -646,48 +518,48 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.817.0.tgz", - "integrity": "sha512-MNGwOJDQU0jpvsLLPSuPQDhPtDzFTc/k7rLmiKoPrIlgb3Y8pSF4crpJ+ZH3+xod2NWyyOVMEMQeMaKFFdMaKw==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.840.0.tgz", + "integrity": "sha512-0sn/X63Xqqh5D1FYmdSHiS9SkDzTitoGO++/8IFik4xf/jpn4ZQkIoDPvpxFZcLvebMuUa6jAQs4ap4RusKGkg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.816.0", - "@aws-sdk/credential-provider-node": "3.817.0", - "@aws-sdk/middleware-host-header": "3.804.0", - "@aws-sdk/middleware-logger": "3.804.0", - "@aws-sdk/middleware-recursion-detection": "3.804.0", - "@aws-sdk/middleware-user-agent": "3.816.0", - "@aws-sdk/region-config-resolver": "3.808.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.808.0", - "@aws-sdk/util-user-agent-browser": "3.804.0", - "@aws-sdk/util-user-agent-node": "3.816.0", - "@smithy/config-resolver": "^4.1.2", - "@smithy/core": "^3.3.3", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.6", - "@smithy/middleware-retry": "^4.1.7", - "@smithy/middleware-serde": "^4.0.5", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.1.1", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.6", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/credential-provider-node": "3.840.0", + "@aws-sdk/middleware-host-header": "3.840.0", + "@aws-sdk/middleware-logger": "3.840.0", + "@aws-sdk/middleware-recursion-detection": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/region-config-resolver": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-user-agent-browser": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.840.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.6.0", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/hash-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.13", + "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.14", - "@smithy/util-defaults-mode-node": "^4.0.14", - "@smithy/util-endpoints": "^3.0.4", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.3", + "@smithy/util-defaults-mode-browser": "^4.0.21", + "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -696,47 +568,47 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.817.0.tgz", - "integrity": "sha512-fCh5rUHmWmWDvw70NNoWpE5+BRdtNi45kDnIoeoszqVg7UKF79SlG+qYooUT52HKCgDNHqgbWaXxMOSqd2I/OQ==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.840.0.tgz", + "integrity": "sha512-3Zp+FWN2hhmKdpS0Ragi5V2ZPsZNScE3jlbgoJjzjI/roHZqO+e3/+XFN4TlM0DsPKYJNp+1TAjmhxN6rOnfYA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.816.0", - "@aws-sdk/middleware-host-header": "3.804.0", - "@aws-sdk/middleware-logger": "3.804.0", - "@aws-sdk/middleware-recursion-detection": "3.804.0", - "@aws-sdk/middleware-user-agent": "3.816.0", - "@aws-sdk/region-config-resolver": "3.808.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.808.0", - "@aws-sdk/util-user-agent-browser": "3.804.0", - "@aws-sdk/util-user-agent-node": "3.816.0", - "@smithy/config-resolver": "^4.1.2", - "@smithy/core": "^3.3.3", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.6", - "@smithy/middleware-retry": "^4.1.7", - "@smithy/middleware-serde": "^4.0.5", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.1.1", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.6", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/middleware-host-header": "3.840.0", + "@aws-sdk/middleware-logger": "3.840.0", + "@aws-sdk/middleware-recursion-detection": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/region-config-resolver": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-user-agent-browser": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.840.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.6.0", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/hash-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.13", + "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.14", - "@smithy/util-defaults-mode-node": "^4.0.14", - "@smithy/util-endpoints": "^3.0.4", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.3", + "@smithy/util-defaults-mode-browser": "^4.0.21", + "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -745,20 +617,24 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.816.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.816.0.tgz", - "integrity": "sha512-Lx50wjtyarzKpMFV6V+gjbSZDgsA/71iyifbClGUSiNPoIQ4OCV0KVOmAAj7mQRVvGJqUMWKVM+WzK79CjbjWA==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.840.0.tgz", + "integrity": "sha512-x3Zgb39tF1h2XpU+yA4OAAQlW6LVEfXNlSedSYJ7HGKXqA/E9h3rWQVpYfhXXVVsLdYXdNw5KBUkoAoruoZSZA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/core": "^3.3.3", - "@smithy/node-config-provider": "^4.1.1", - "@smithy/property-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/signature-v4": "^5.1.0", - "@smithy/smithy-client": "^4.2.6", - "@smithy/types": "^4.2.0", - "@smithy/util-middleware": "^4.0.2", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/xml-builder": "3.821.0", + "@smithy/core": "^3.6.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/signature-v4": "^5.1.2", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-utf8": "^4.0.0", "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, @@ -767,15 +643,15 @@ } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.817.0.tgz", - "integrity": "sha512-+dzgWGmdmMNDdeSF+VvONN+hwqoGKX5A6Z3+siMO4CIoKWN7u5nDOx/JLjTGdVQji3522pJjJ+o9veQJNWOMRg==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.840.0.tgz", + "integrity": "sha512-p1RaMVd6+6ruYjKsWRCZT/jWhrYfDKbXY+/ScIYTvcaOOf9ArMtVnhFk3egewrC7kPXFGRYhg2GPmxRotNYMng==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.817.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/client-cognito-identity": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -783,15 +659,15 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.816.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.816.0.tgz", - "integrity": "sha512-wUJZwRLe+SxPxRV9AENYBLrJZRrNIo+fva7ZzejsC83iz7hdfq6Rv6B/aHEdPwG/nQC4+q7UUvcRPlomyrpsBA==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.840.0.tgz", + "integrity": "sha512-EzF6VcJK7XvQ/G15AVEfJzN2mNXU8fcVpXo4bRyr1S6t2q5zx6UPH/XjDbn18xyUmOq01t+r8gG+TmHEVo18fA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.816.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -799,20 +675,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.816.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.816.0.tgz", - "integrity": "sha512-gcWGzMQ7yRIF+ljTkR8Vzp7727UY6cmeaPrFQrvcFB8PhOqWpf7g0JsgOf5BSaP8CkkSQcTQHc0C5ZYAzUFwPg==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.840.0.tgz", + "integrity": "sha512-wbnUiPGLVea6mXbUh04fu+VJmGkQvmToPeTYdHE8eRZq3NRDi3t3WltT+jArLBKD/4NppRpMjf2ju4coMCz91g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.816.0", - "@aws-sdk/types": "3.804.0", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/property-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.6", - "@smithy/types": "^4.2.0", - "@smithy/util-stream": "^4.2.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", + "@smithy/util-stream": "^4.2.2", "tslib": "^2.6.2" }, "engines": { @@ -820,23 +696,23 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.817.0.tgz", - "integrity": "sha512-kyEwbQyuXE+phWVzloMdkFv6qM6NOon+asMXY5W0fhDKwBz9zQLObDRWBrvQX9lmqq8BbDL1sCfZjOh82Y+RFw==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.840.0.tgz", + "integrity": "sha512-7F290BsWydShHb+7InXd+IjJc3mlEIm9I0R57F/Pjl1xZB69MdkhVGCnuETWoBt4g53ktJd6NEjzm/iAhFXFmw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.816.0", - "@aws-sdk/credential-provider-env": "3.816.0", - "@aws-sdk/credential-provider-http": "3.816.0", - "@aws-sdk/credential-provider-process": "3.816.0", - "@aws-sdk/credential-provider-sso": "3.817.0", - "@aws-sdk/credential-provider-web-identity": "3.817.0", - "@aws-sdk/nested-clients": "3.817.0", - "@aws-sdk/types": "3.804.0", - "@smithy/credential-provider-imds": "^4.0.4", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/credential-provider-env": "3.840.0", + "@aws-sdk/credential-provider-http": "3.840.0", + "@aws-sdk/credential-provider-process": "3.840.0", + "@aws-sdk/credential-provider-sso": "3.840.0", + "@aws-sdk/credential-provider-web-identity": "3.840.0", + "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -844,22 +720,22 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.817.0.tgz", - "integrity": "sha512-b5mz7av0Lhavs1Bz3Zb+jrs0Pki93+8XNctnVO0drBW98x1fM4AR38cWvGbM/w9F9Q0/WEH3TinkmrMPrP4T/w==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.840.0.tgz", + "integrity": "sha512-KufP8JnxA31wxklLm63evUPSFApGcH8X86z3mv9SRbpCm5ycgWIGVCTXpTOdgq6rPZrwT9pftzv2/b4mV/9clg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.816.0", - "@aws-sdk/credential-provider-http": "3.816.0", - "@aws-sdk/credential-provider-ini": "3.817.0", - "@aws-sdk/credential-provider-process": "3.816.0", - "@aws-sdk/credential-provider-sso": "3.817.0", - "@aws-sdk/credential-provider-web-identity": "3.817.0", - "@aws-sdk/types": "3.804.0", - "@smithy/credential-provider-imds": "^4.0.4", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/credential-provider-env": "3.840.0", + "@aws-sdk/credential-provider-http": "3.840.0", + "@aws-sdk/credential-provider-ini": "3.840.0", + "@aws-sdk/credential-provider-process": "3.840.0", + "@aws-sdk/credential-provider-sso": "3.840.0", + "@aws-sdk/credential-provider-web-identity": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -867,16 +743,16 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.816.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.816.0.tgz", - "integrity": "sha512-9Tm+AxMoV2Izvl5b9tyMQRbBwaex8JP06HN7ZeCXgC5sAsSN+o8dsThnEhf8jKN+uBpT6CLWKN1TXuUMrAmW1A==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.840.0.tgz", + "integrity": "sha512-HkDQWHy8tCI4A0Ps2NVtuVYMv9cB4y/IuD/TdOsqeRIAT12h8jDb98BwQPNLAImAOwOWzZJ8Cu0xtSpX7CQhMw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.816.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -884,18 +760,18 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.817.0.tgz", - "integrity": "sha512-gFUAW3VmGvdnueK1bh6TOcRX+j99Xm0men1+gz3cA4RE+rZGNy1Qjj8YHlv0hPwI9OnTPZquvPzA5fkviGREWg==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.840.0.tgz", + "integrity": "sha512-2qgdtdd6R0Z1y0KL8gzzwFUGmhBHSUx4zy85L2XV1CXhpRNwV71SVWJqLDVV5RVWVf9mg50Pm3AWrUC0xb0pcA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.817.0", - "@aws-sdk/core": "3.816.0", - "@aws-sdk/token-providers": "3.817.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/client-sso": "3.840.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/token-providers": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -903,16 +779,16 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.817.0.tgz", - "integrity": "sha512-A2kgkS9g6NY0OMT2f2EdXHpL17Ym81NhbGnQ8bRXPqESIi7TFypFD2U6osB2VnsFv+MhwM+Ke4PKXSmLun22/A==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.840.0.tgz", + "integrity": "sha512-dpEeVXG8uNZSmVXReE4WP0lwoioX2gstk4RnUgrdUE3YaPq8A+hJiVAyc3h+cjDeIqfbsQbZm9qFetKC2LF9dQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.816.0", - "@aws-sdk/nested-clients": "3.817.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -920,29 +796,29 @@ } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.817.0.tgz", - "integrity": "sha512-i6Q2MyktWHG4YG+EmLlnXTgNVjW9/yeNHSKzF55GTho5fjqfU+t9beJfuMWclanRCifamm3N5e5OCm52rVDdTQ==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.840.0.tgz", + "integrity": "sha512-+CxYdGd+uM4NZ9VUvFTU1c/H61qhDB4q362k8xKU+bz24g//LDQ5Mpwksv8OUD1en44v4fUwgZ4SthPZMs+eFQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.817.0", - "@aws-sdk/core": "3.816.0", - "@aws-sdk/credential-provider-cognito-identity": "3.817.0", - "@aws-sdk/credential-provider-env": "3.816.0", - "@aws-sdk/credential-provider-http": "3.816.0", - "@aws-sdk/credential-provider-ini": "3.817.0", - "@aws-sdk/credential-provider-node": "3.817.0", - "@aws-sdk/credential-provider-process": "3.816.0", - "@aws-sdk/credential-provider-sso": "3.817.0", - "@aws-sdk/credential-provider-web-identity": "3.817.0", - "@aws-sdk/nested-clients": "3.817.0", - "@aws-sdk/types": "3.804.0", - "@smithy/config-resolver": "^4.1.2", - "@smithy/core": "^3.3.3", - "@smithy/credential-provider-imds": "^4.0.4", - "@smithy/node-config-provider": "^4.1.1", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/client-cognito-identity": "3.840.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/credential-provider-cognito-identity": "3.840.0", + "@aws-sdk/credential-provider-env": "3.840.0", + "@aws-sdk/credential-provider-http": "3.840.0", + "@aws-sdk/credential-provider-ini": "3.840.0", + "@aws-sdk/credential-provider-node": "3.840.0", + "@aws-sdk/credential-provider-process": "3.840.0", + "@aws-sdk/credential-provider-sso": "3.840.0", + "@aws-sdk/credential-provider-web-identity": "3.840.0", + "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.6.0", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -950,14 +826,14 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.804.0.tgz", - "integrity": "sha512-bum1hLVBrn2lJCi423Z2fMUYtsbkGI2s4N+2RI2WSjvbaVyMSv/WcejIrjkqiiMR+2Y7m5exgoKeg4/TODLDPQ==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.840.0.tgz", + "integrity": "sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/types": "3.840.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -965,13 +841,13 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.804.0.tgz", - "integrity": "sha512-w/qLwL3iq0KOPQNat0Kb7sKndl9BtceigINwBU7SpkYWX9L/Lem6f8NPEKrC9Tl4wDBht3Yztub4oRTy/horJA==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.840.0.tgz", + "integrity": "sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -979,14 +855,14 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.804.0.tgz", - "integrity": "sha512-zqHOrvLRdsUdN/ehYfZ9Tf8svhbiLLz5VaWUz22YndFv6m9qaAcijkpAOlKexsv3nLBMJdSdJ6GUTAeIy3BZzw==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.840.0.tgz", + "integrity": "sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/types": "3.840.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -994,17 +870,17 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.816.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.816.0.tgz", - "integrity": "sha512-bHRSlWZ0xDsFR8E2FwDb//0Ff6wMkVx4O+UKsfyNlAbtqCiiHRt5ANNfKPafr95cN2CCxLxiPvFTFVblQM5TsQ==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.840.0.tgz", + "integrity": "sha512-hiiMf7BP5ZkAFAvWRcK67Mw/g55ar7OCrvrynC92hunx/xhMkrgSLM0EXIZ1oTn3uql9kH/qqGF0nqsK6K555A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.816.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.808.0", - "@smithy/core": "^3.3.3", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.840.0", + "@smithy/core": "^3.6.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -1012,47 +888,47 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.817.0.tgz", - "integrity": "sha512-vQ2E06A48STJFssueJQgxYD8lh1iGJoLJnHdshRDWOQb8gy1wVQR+a7MkPGhGR6lGoS0SCnF/Qp6CZhnwLsqsQ==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.840.0.tgz", + "integrity": "sha512-LXYYo9+n4hRqnRSIMXLBb+BLz+cEmjMtTudwK1BF6Bn2RfdDv29KuyeDRrPCS3TwKl7ZKmXUmE9n5UuHAPfBpA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.816.0", - "@aws-sdk/middleware-host-header": "3.804.0", - "@aws-sdk/middleware-logger": "3.804.0", - "@aws-sdk/middleware-recursion-detection": "3.804.0", - "@aws-sdk/middleware-user-agent": "3.816.0", - "@aws-sdk/region-config-resolver": "3.808.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.808.0", - "@aws-sdk/util-user-agent-browser": "3.804.0", - "@aws-sdk/util-user-agent-node": "3.816.0", - "@smithy/config-resolver": "^4.1.2", - "@smithy/core": "^3.3.3", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.6", - "@smithy/middleware-retry": "^4.1.7", - "@smithy/middleware-serde": "^4.0.5", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.1.1", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.6", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/middleware-host-header": "3.840.0", + "@aws-sdk/middleware-logger": "3.840.0", + "@aws-sdk/middleware-recursion-detection": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/region-config-resolver": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.840.0", + "@aws-sdk/util-user-agent-browser": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.840.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.6.0", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/hash-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.13", + "@smithy/middleware-retry": "^4.1.14", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.14", - "@smithy/util-defaults-mode-node": "^4.0.14", - "@smithy/util-endpoints": "^3.0.4", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.3", + "@smithy/util-defaults-mode-browser": "^4.0.21", + "@smithy/util-defaults-mode-node": "^4.0.21", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1061,16 +937,16 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.808.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.808.0.tgz", - "integrity": "sha512-9x2QWfphkARZY5OGkl9dJxZlSlYM2l5inFeo2bKntGuwg4A4YUe5h7d5yJ6sZbam9h43eBrkOdumx03DAkQF9A==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.840.0.tgz", + "integrity": "sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/node-config-provider": "^4.1.1", - "@smithy/types": "^4.2.0", + "@aws-sdk/types": "3.840.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.2", + "@smithy/util-middleware": "^4.0.4", "tslib": "^2.6.2" }, "engines": { @@ -1078,17 +954,17 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.817.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.817.0.tgz", - "integrity": "sha512-CYN4/UO0VaqyHf46ogZzNrVX7jI3/CfiuktwKlwtpKA6hjf2+ivfgHSKzPpgPBcSEfiibA/26EeLuMnB6cpSrQ==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.840.0.tgz", + "integrity": "sha512-6BuTOLTXvmgwjK7ve7aTg9JaWFdM5UoMolLVPMyh3wTv9Ufalh8oklxYHUBIxsKkBGO2WiHXytveuxH6tAgTYg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.816.0", - "@aws-sdk/nested-clients": "3.817.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.840.0", + "@aws-sdk/nested-clients": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -1096,12 +972,12 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.804.0.tgz", - "integrity": "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.840.0.tgz", + "integrity": "sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.2.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -1109,14 +985,14 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.808.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.808.0.tgz", - "integrity": "sha512-N6Lic98uc4ADB7fLWlzx+1uVnq04VgVjngZvwHoujcRg9YDhIg9dUDiTzD5VZv13g1BrPYmvYP1HhsildpGV6w==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.840.0.tgz", + "integrity": "sha512-eqE9ROdg/Kk0rj3poutyRCFauPDXIf/WSvCqFiRDDVi6QOnCv/M0g2XW8/jSvkJlOyaXkNCptapIp6BeeFFGYw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", - "@smithy/util-endpoints": "^3.0.4", + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", + "@smithy/util-endpoints": "^3.0.6", "tslib": "^2.6.2" }, "engines": { @@ -1136,27 +1012,27 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.804.0.tgz", - "integrity": "sha512-KfW6T6nQHHM/vZBBdGn6fMyG/MgX5lq82TDdX4HRQRRuHKLgBWGpKXqqvBwqIaCdXwWHgDrg2VQups6GqOWW2A==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.840.0.tgz", + "integrity": "sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.816.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.816.0.tgz", - "integrity": "sha512-Q6dxmuj4hL7pudhrneWEQ7yVHIQRBFr0wqKLF1opwOi1cIePuoEbPyJ2jkel6PDEv1YMfvsAKaRshp6eNA8VHg==", + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.840.0.tgz", + "integrity": "sha512-Fy5JUEDQU1tPm2Yw/YqRYYc27W5+QD/J4mYvQvdWjUGZLB5q3eLFMGD35Uc28ZFoGMufPr4OCxK/bRfWROBRHQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.816.0", - "@aws-sdk/types": "3.804.0", - "@smithy/node-config-provider": "^4.1.1", - "@smithy/types": "^4.2.0", + "@aws-sdk/middleware-user-agent": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -1171,25 +1047,38 @@ } } }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.821.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.821.0.tgz", + "integrity": "sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.7.tgz", + "integrity": "sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ==", "dev": true, "license": "MIT", "engines": { @@ -1197,22 +1086,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", + "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.27.7", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.7", + "@babel/types": "^7.27.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1227,15 +1116,50 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/generator": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", - "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", + "node_modules/@babel/core/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.10", - "@babel/types": "^7.26.10", + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -1245,14 +1169,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -1271,30 +1195,40 @@ "yallist": "^3.0.2" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -1304,9 +1238,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "license": "MIT", "engines": { @@ -1314,9 +1248,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -1324,9 +1258,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "license": "MIT", "engines": { @@ -1334,9 +1268,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -1344,27 +1278,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", - "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", - "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", + "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.10" + "@babel/types": "^7.27.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -1429,13 +1363,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1471,13 +1405,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1597,13 +1531,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1613,45 +1547,42 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", "dev": true, "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", - "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.7.tgz", + "integrity": "sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.5", + "@babel/parser": "^7.27.7", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1659,15 +1590,40 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/types": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", - "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", + "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1845,15 +1801,15 @@ } }, "node_modules/@changesets/apply-release-plan": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.10.tgz", - "integrity": "sha512-wNyeIJ3yDsVspYvHnEz1xQDq18D9ifed3lI+wxRQRK4pArUcuHgCTrHv0QRnnwjhVCQACxZ+CBih3wgOct6UXw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.12.tgz", + "integrity": "sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ==", "dev": true, "license": "MIT", "dependencies": { "@changesets/config": "^3.1.1", "@changesets/get-version-range-type": "^0.4.0", - "@changesets/git": "^3.0.2", + "@changesets/git": "^3.0.4", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", @@ -1882,23 +1838,10 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/@changesets/apply-release-plan/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@changesets/assemble-release-plan": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.6.tgz", - "integrity": "sha512-Frkj8hWJ1FRZiY3kzVCKzS0N5mMwWKwmv9vpam7vt8rZjLL1JMthdh6pSDVSPumHPshTTkKZ0VtNbE0cJHZZUg==", + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.9.tgz", + "integrity": "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1910,19 +1853,6 @@ "semver": "^7.5.3" } }, - "node_modules/@changesets/assemble-release-plan/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@changesets/changelog-git": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz", @@ -1956,23 +1886,23 @@ } }, "node_modules/@changesets/cli": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.28.1.tgz", - "integrity": "sha512-PiIyGRmSc6JddQJe/W1hRPjiN4VrMvb2VfQ6Uydy2punBioQrsxppyG5WafinKcW1mT0jOe/wU4k9Zy5ff21AA==", + "version": "2.29.5", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.29.5.tgz", + "integrity": "sha512-0j0cPq3fgxt2dPdFsg4XvO+6L66RC0pZybT9F4dG5TBrLA3jA/1pNkdTXH9IBBVHkgsKrNKenI3n1mPyPlIydg==", "dev": true, "license": "MIT", "dependencies": { - "@changesets/apply-release-plan": "^7.0.10", - "@changesets/assemble-release-plan": "^6.0.6", + "@changesets/apply-release-plan": "^7.0.12", + "@changesets/assemble-release-plan": "^6.0.9", "@changesets/changelog-git": "^0.2.1", "@changesets/config": "^3.1.1", "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", - "@changesets/get-release-plan": "^4.0.8", - "@changesets/git": "^3.0.2", + "@changesets/get-release-plan": "^4.0.13", + "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/pre": "^2.0.2", - "@changesets/read": "^0.6.3", + "@changesets/read": "^0.6.5", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@changesets/write": "^0.4.0", @@ -1995,35 +1925,6 @@ "changeset": "bin.js" } }, - "node_modules/@changesets/cli/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@changesets/cli/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@changesets/config": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.1.tgz", @@ -2063,19 +1964,6 @@ "semver": "^7.5.3" } }, - "node_modules/@changesets/get-dependents-graph/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@changesets/get-github-info": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@changesets/get-github-info/-/get-github-info-0.6.0.tgz", @@ -2087,38 +1975,17 @@ "node-fetch": "^2.5.0" } }, - "node_modules/@changesets/get-github-info/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/@changesets/get-release-plan": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.8.tgz", - "integrity": "sha512-MM4mq2+DQU1ZT7nqxnpveDMTkMBLnwNX44cX7NSxlXmr7f8hO6/S2MXNiXG54uf/0nYnefv0cfy4Czf/ZL/EKQ==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.13.tgz", + "integrity": "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==", "dev": true, "license": "MIT", "dependencies": { - "@changesets/assemble-release-plan": "^6.0.6", + "@changesets/assemble-release-plan": "^6.0.9", "@changesets/config": "^3.1.1", "@changesets/pre": "^2.0.2", - "@changesets/read": "^0.6.3", + "@changesets/read": "^0.6.5", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } @@ -2131,9 +1998,9 @@ "license": "MIT" }, "node_modules/@changesets/git": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.2.tgz", - "integrity": "sha512-r1/Kju9Y8OxRRdvna+nxpQIsMsRQn9dhhAZt94FLDeu0Hij2hnOozW8iqnHBgvu+KdnJppCveQwK4odwfw/aWQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz", + "integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==", "dev": true, "license": "MIT", "dependencies": { @@ -2179,13 +2046,13 @@ } }, "node_modules/@changesets/read": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.3.tgz", - "integrity": "sha512-9H4p/OuJ3jXEUTjaVGdQEhBdqoT2cO5Ts95JTFsQyawmKzpL8FnIeJSyhTDPW1MBRDnwZlHFEM9SpPwJDY5wIg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.5.tgz", + "integrity": "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==", "dev": true, "license": "MIT", "dependencies": { - "@changesets/git": "^3.0.2", + "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/parse": "^0.4.1", "@changesets/types": "^6.1.0", @@ -2252,9 +2119,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", - "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", "cpu": [ "ppc64" ], @@ -2269,9 +2136,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", - "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", "cpu": [ "arm" ], @@ -2286,9 +2153,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", - "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", "cpu": [ "arm64" ], @@ -2303,9 +2170,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", - "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", "cpu": [ "x64" ], @@ -2320,9 +2187,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", - "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", "cpu": [ "arm64" ], @@ -2337,9 +2204,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", - "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", "cpu": [ "x64" ], @@ -2354,9 +2221,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", - "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", "cpu": [ "arm64" ], @@ -2371,9 +2238,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", - "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", "cpu": [ "x64" ], @@ -2388,9 +2255,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", - "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", "cpu": [ "arm" ], @@ -2405,9 +2272,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", - "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", "cpu": [ "arm64" ], @@ -2422,9 +2289,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", - "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", "cpu": [ "ia32" ], @@ -2439,9 +2306,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", - "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", "cpu": [ "loong64" ], @@ -2456,9 +2323,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", - "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", "cpu": [ "mips64el" ], @@ -2473,9 +2340,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", - "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", "cpu": [ "ppc64" ], @@ -2490,9 +2357,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", - "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", "cpu": [ "riscv64" ], @@ -2507,9 +2374,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", - "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", "cpu": [ "s390x" ], @@ -2524,9 +2391,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", - "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", "cpu": [ "x64" ], @@ -2541,9 +2408,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", - "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", "cpu": [ "arm64" ], @@ -2558,9 +2425,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", - "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", "cpu": [ "x64" ], @@ -2575,9 +2442,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", - "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", "cpu": [ "arm64" ], @@ -2592,9 +2459,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", - "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", "cpu": [ "x64" ], @@ -2609,9 +2476,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", - "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", "cpu": [ "x64" ], @@ -2626,9 +2493,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", - "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", "cpu": [ "arm64" ], @@ -2643,9 +2510,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", - "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", "cpu": [ "ia32" ], @@ -2660,9 +2527,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", - "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", "cpu": [ "x64" ], @@ -2676,6 +2543,98 @@ "node": ">=18" } }, + "node_modules/@google/gemini-cli-core": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@google/gemini-cli-core/-/gemini-cli-core-0.1.7.tgz", + "integrity": "sha512-V3KYamCruqhBSoWNvWm5MJn6EwwZVv/129h0f2SFVfgJP759QVAvcnT4nGq18Jf5nNqDkq01Uug3yR/NfGJN+g==", + "optional": true, + "dependencies": { + "@google/genai": "^1.4.0", + "@modelcontextprotocol/sdk": "^1.11.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/exporter-logs-otlp-grpc": "^0.52.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "^0.52.0", + "@opentelemetry/exporter-trace-otlp-grpc": "^0.52.0", + "@opentelemetry/instrumentation-http": "^0.52.0", + "@opentelemetry/sdk-node": "^0.52.0", + "@types/glob": "^8.1.0", + "@types/html-to-text": "^9.0.4", + "diff": "^7.0.0", + "dotenv": "^16.4.7", + "gaxios": "^6.1.1", + "glob": "^10.4.5", + "google-auth-library": "^9.11.0", + "html-to-text": "^9.0.5", + "ignore": "^7.0.0", + "micromatch": "^4.0.8", + "open": "^10.1.2", + "shell-quote": "^1.8.2", + "simple-git": "^3.28.0", + "strip-ansi": "^7.1.0", + "undici": "^7.10.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google/genai": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.7.0.tgz", + "integrity": "sha512-s/OZLkrIfBwc+SFFaZoKdEogkw4in0YRTGc4Q483jnfchNBWzrNe560eZEfGJHQRPn6YfzJgECCx0sqEOMWvYw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "google-auth-library": "^9.14.2", + "ws": "^8.18.0", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.22.4" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.11.0" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz", + "integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", + "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", @@ -2886,14 +2845,14 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.4.tgz", - "integrity": "sha512-d30576EZdApjAMceijXA5jDzRQHT/MygbC+J8I7EqA6f/FRpYxlRtRJbHF8gHeWYeSdOuTEJqonn7QLB1ELezA==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.8.tgz", + "integrity": "sha512-d/QAsnwuHX2OPolxvYcgSj7A9DO9H6gVOy2DvBTx+P2LH2iRTo/RSGV3iwCzW024nP9hw98KIuDmdyhZQj1UQg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", + "@inquirer/core": "^10.1.13", + "@inquirer/figures": "^1.0.12", + "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, @@ -2910,13 +2869,13 @@ } }, "node_modules/@inquirer/confirm": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.8.tgz", - "integrity": "sha512-dNLWCYZvXDjO3rnQfk2iuJNL4Ivwz/T2+C3+WnNfJKsNGSuOs3wAo2F6e0p946gtSAk31nZMfW+MRmYaplPKsg==", + "version": "5.1.12", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.12.tgz", + "integrity": "sha512-dpq+ielV9/bqgXRUbNH//KsY6WEw9DrGPmipkpmgC1Y46cwuBTNx7PXFWTjc3MQ+urcc0QxoVHcMI0FW4Ok0hg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/type": "^3.0.5" + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7" }, "engines": { "node": ">=18" @@ -2957,69 +2916,14 @@ } } }, - "node_modules/@inquirer/core/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/core/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/@inquirer/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/core/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@inquirer/editor": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.9.tgz", - "integrity": "sha512-8HjOppAxO7O4wV1ETUlJFg6NDjp/W2NP5FB9ZPAcinAlNT4ZIWOLe2pUVwmmPRSV0NMdI5r/+lflN55AwZOKSw==", + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.13.tgz", + "integrity": "sha512-WbicD9SUQt/K8O5Vyk9iC2ojq5RHoCLK6itpp2fHsWe44VxxcA9z3GTWlvjSTGmMQpZr+lbVmrxdHcumJoLbMA==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/type": "^3.0.5", + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7", "external-editor": "^3.1.0" }, "engines": { @@ -3035,13 +2939,13 @@ } }, "node_modules/@inquirer/expand": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.11.tgz", - "integrity": "sha512-OZSUW4hFMW2TYvX/Sv+NnOZgO8CHT2TU1roUCUIF2T+wfw60XFRRp9MRUPCT06cRnKL+aemt2YmTWwt7rOrNEA==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.15.tgz", + "integrity": "sha512-4Y+pbr/U9Qcvf+N/goHzPEXiHH8680lM3Dr3Y9h9FFw4gHS+zVpbj8LfbKWIb/jayIB4aSO4pWiBTrBYWkvi5A==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/type": "^3.0.5", + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7", "yoctocolors-cjs": "^2.1.2" }, "engines": { @@ -3066,13 +2970,13 @@ } }, "node_modules/@inquirer/input": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.8.tgz", - "integrity": "sha512-WXJI16oOZ3/LiENCAxe8joniNp8MQxF6Wi5V+EBbVA0ZIOpFcL4I9e7f7cXse0HJeIPCWO8Lcgnk98juItCi7Q==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.12.tgz", + "integrity": "sha512-xJ6PFZpDjC+tC1P8ImGprgcsrzQRsUh9aH3IZixm1lAZFK49UGHxM3ltFfuInN2kPYNfyoPRh+tU4ftsjPLKqQ==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/type": "^3.0.5" + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7" }, "engines": { "node": ">=18" @@ -3087,13 +2991,13 @@ } }, "node_modules/@inquirer/number": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.11.tgz", - "integrity": "sha512-pQK68CsKOgwvU2eA53AG/4npRTH2pvs/pZ2bFvzpBhrznh8Mcwt19c+nMO7LHRr3Vreu1KPhNBF3vQAKrjIulw==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.15.tgz", + "integrity": "sha512-xWg+iYfqdhRiM55MvqiTCleHzszpoigUpN5+t1OMcRkJrUrw7va3AzXaxvS+Ak7Gny0j2mFSTv2JJj8sMtbV2g==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/type": "^3.0.5" + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7" }, "engines": { "node": ">=18" @@ -3108,13 +3012,13 @@ } }, "node_modules/@inquirer/password": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.11.tgz", - "integrity": "sha512-dH6zLdv+HEv1nBs96Case6eppkRggMe8LoOTl30+Gq5Wf27AO/vHFgStTVz4aoevLdNXqwE23++IXGw4eiOXTg==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.15.tgz", + "integrity": "sha512-75CT2p43DGEnfGTaqFpbDC2p2EEMrq0S+IRrf9iJvYreMy5mAWj087+mdKyLHapUEPLjN10mNvABpGbk8Wdraw==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/type": "^3.0.5", + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2" }, "engines": { @@ -3130,21 +3034,21 @@ } }, "node_modules/@inquirer/prompts": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.4.0.tgz", - "integrity": "sha512-EZiJidQOT4O5PYtqnu1JbF0clv36oW2CviR66c7ma4LsupmmQlUwmdReGKRp456OWPWMz3PdrPiYg3aCk3op2w==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.5.3.tgz", + "integrity": "sha512-8YL0WiV7J86hVAxrh3fE5mDCzcTDe1670unmJRz6ArDgN+DBK1a0+rbnNWp4DUB5rPMwqD5ZP6YHl9KK1mbZRg==", "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^4.1.4", - "@inquirer/confirm": "^5.1.8", - "@inquirer/editor": "^4.2.9", - "@inquirer/expand": "^4.0.11", - "@inquirer/input": "^4.1.8", - "@inquirer/number": "^3.0.11", - "@inquirer/password": "^4.0.11", - "@inquirer/rawlist": "^4.0.11", - "@inquirer/search": "^3.0.11", - "@inquirer/select": "^4.1.0" + "@inquirer/checkbox": "^4.1.8", + "@inquirer/confirm": "^5.1.12", + "@inquirer/editor": "^4.2.13", + "@inquirer/expand": "^4.0.15", + "@inquirer/input": "^4.1.12", + "@inquirer/number": "^3.0.15", + "@inquirer/password": "^4.0.15", + "@inquirer/rawlist": "^4.1.3", + "@inquirer/search": "^3.0.15", + "@inquirer/select": "^4.2.3" }, "engines": { "node": ">=18" @@ -3159,13 +3063,13 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.11.tgz", - "integrity": "sha512-uAYtTx0IF/PqUAvsRrF3xvnxJV516wmR6YVONOmCWJbbt87HcDHLfL9wmBQFbNJRv5kCjdYKrZcavDkH3sVJPg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.3.tgz", + "integrity": "sha512-7XrV//6kwYumNDSsvJIPeAqa8+p7GJh7H5kRuxirct2cgOcSWwwNGoXDRgpNFbY/MG2vQ4ccIWCi8+IXXyFMZA==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/type": "^3.0.5", + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7", "yoctocolors-cjs": "^2.1.2" }, "engines": { @@ -3204,14 +3108,14 @@ } }, "node_modules/@inquirer/select": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.1.0.tgz", - "integrity": "sha512-z0a2fmgTSRN+YBuiK1ROfJ2Nvrpij5lVN3gPDkQGhavdvIVGHGW29LwYZfM/j42Ai2hUghTI/uoBuTbrJk42bA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.2.3.tgz", + "integrity": "sha512-OAGhXU0Cvh0PhLz9xTF/kx6g6x+sP+PcyTiLvCrewI99P3BBeexD+VbuwkNDvqGkk3y2h5ZiWLeRP7BFlhkUDg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.5", + "@inquirer/core": "^10.1.13", + "@inquirer/figures": "^1.0.12", + "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, @@ -3244,6 +3148,67 @@ } } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT", + "optional": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "optional": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -3299,6 +3264,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@jest/console/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3374,6 +3355,22 @@ "node": ">=8" } }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@jest/core/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3535,6 +3532,33 @@ "node": ">=8" } }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/@jest/reporters/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3552,6 +3576,41 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "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": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@jest/reporters/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3652,6 +3711,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@jest/transform/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3687,6 +3762,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@jest/types/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3705,18 +3796,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.11.tgz", + "integrity": "sha512-C512c1ytBTio4MrpWKlJpyFHT6+qfFL8SZ58zBzJ1OOzUEjHeF1BtjY2fH7n4x/g2OV/KiiMLAivOp1DXmiMMw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -3729,27 +3816,17 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.3.tgz", + "integrity": "sha512-AiR5uKpFxP3PjO4R19kQGIMwxyRyPuXmKEEy301V1C0+1rVjS94EZQXf1QKZYN8Q0YM+estSPhmx5JwNftv6nw==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.28", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.28.tgz", + "integrity": "sha512-KNNHHwW3EIp4EDYOvYFGyIFfx36R2dNJYH4knnZlF8T5jdbD5Wx8xmSaQ2gP9URkJ04LGEtlcCtwArKcmFcwKw==", "dev": true, "license": "MIT", "dependencies": { @@ -3757,6 +3834,59 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/file-exists/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@kwsites/file-exists/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "license": "MIT", + "optional": true + }, "node_modules/@manypkg/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", @@ -3830,9 +3960,9 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.3.tgz", - "integrity": "sha512-DyVYSOafBvk3/j1Oka4z5BWT8o4AFmoNyZY9pALOm7Lh3GZglR71Co4r4dEUoqDWdDazIZQHBe7J2Nwkg6gHgQ==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.13.3.tgz", + "integrity": "sha512-bGwA78F/U5G2jrnsdRkPY3IwIwZeWUEfb5o764b79lb0rJmMT76TLwKhdNZOWakOQtedYefwIR4emisEMvInKA==", "license": "MIT", "dependencies": { "ajv": "^6.12.6", @@ -3840,6 +3970,7 @@ "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", @@ -3905,6 +4036,23 @@ "node": ">=6.6.0" } }, + "node_modules/@modelcontextprotocol/sdk/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/@modelcontextprotocol/sdk/node_modules/express": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", @@ -4027,6 +4175,12 @@ "node": ">= 0.6" } }, + "node_modules/@modelcontextprotocol/sdk/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -4036,19 +4190,19 @@ "node": ">= 0.6" } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "license": "MIT", + "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" + "side-channel": "^1.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/@modelcontextprotocol/sdk/node_modules/send": { @@ -4154,9 +4308,9 @@ } }, "node_modules/@openrouter/ai-sdk-provider": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@openrouter/ai-sdk-provider/-/ai-sdk-provider-0.4.5.tgz", - "integrity": "sha512-gbCOcSjNhyWlLHyYZX2rIFnpJi3C2RXNyyzJj+d6pMRfTS/mdvEEOsU66KxK9H8Qju2i9YRLOn/FdQT26K7bIQ==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@openrouter/ai-sdk-provider/-/ai-sdk-provider-0.4.6.tgz", + "integrity": "sha512-oUa8xtssyUhiKEU/aW662lsZ0HUvIUTRk8vVIF3Ha3KI/DnqX54zmVIuzYnaDpermqhy18CHqblAY4dDt1JW3g==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.0.9", @@ -4213,6 +4367,451 @@ "node": ">=8.0.0" } }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.25.1.tgz", + "integrity": "sha512-UW/ge9zjvAEmRWVapOP0qyCvPulWU6cQxGxDbWEFfGOj1VBBZAuOqTo3X6yWmDTD3Xe15ysCZChHncr2xFMIfQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.25.1.tgz", + "integrity": "sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.52.1.tgz", + "integrity": "sha512-sXgcp4fsL3zCo96A0LmFIGYOj2LSEDI6wD7nBYRhuDDxeRsk18NQgqRVlCf4VIyTBZzGu1M7yOtdFukQPgII1A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-grpc-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/sdk-logs": "0.52.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.52.1.tgz", + "integrity": "sha512-CE0f1IEE1GQj8JWl/BxKvKwx9wBTLR09OpPQHaIs5LGBw3ODu8ek5kcbrHPNsFYh/pWh+pcjbZQoxq3CqvQVnA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.52.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-grpc-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-metrics": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.52.1.tgz", + "integrity": "sha512-oAHPOy1sZi58bwqXaucd19F/v7+qE2EuVslQOEeLQT94CDuZJJ4tbWzx8DpYBTrOSzKqqrMtx9+PMxkrcbxOyQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-metrics": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.52.1.tgz", + "integrity": "sha512-pVkSH20crBwMTqB3nIN4jpQKUEoB0Z94drIHpYyEqs7UBr+I0cpYyOR3bqjA/UasQUMROb3GX8ZX4/9cVRqGBQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-grpc-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.52.1.tgz", + "integrity": "sha512-05HcNizx0BxcFKKnS5rwOV+2GevLTVIRA0tRgWYyw4yCgR53Ic/xk83toYKts7kbzcI+dswInUg/4s8oyA+tqg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.52.1.tgz", + "integrity": "sha512-pt6uX0noTQReHXNeEslQv7x311/F1gJzMnp1HD2qgypLRPbXDeMzzeTngRTUaUbP6hqWNtPxuLr4DEoZG+TcEQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.25.1.tgz", + "integrity": "sha512-RmOwSvkimg7ETwJbUOPTMhJm9A9bG1U8s7Zo3ajDh4zM7eYcycQ0dM7FbLD6NXWbI2yj7UY4q8BKinKYBQksyw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.52.1.tgz", + "integrity": "sha512-dG/aevWhaP+7OLv4BQQSEKMJv8GyeOp3Wxl31NHqE8xo9/fYMfEljiZphUHIfyg4gnZ9swMyWjfOQs5GUQe54Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/instrumentation": "0.52.1", + "@opentelemetry/semantic-conventions": "1.25.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.52.1.tgz", + "integrity": "sha512-z175NXOtX5ihdlshtYBe5RpGeBoTXVCKPPLiQlD6FHvpM4Ch+p2B0yWKYSrBfLH24H9zjJiBdTrtD+hLlfnXEQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-transformer": "0.52.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.52.1.tgz", + "integrity": "sha512-zo/YrSDmKMjG+vPeA9aBBrsQM9Q/f2zo6N04WMB3yNldJRsgpRBeLLwvAt/Ba7dpehDLOEFBd1i2JCoaFtpCoQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.52.1.tgz", + "integrity": "sha512-I88uCZSZZtVa0XniRqQWKbjAUm73I8tpEy/uJYPPYw5d7BRdVk0RfTBQw8kSUl01oVWEuqxLDa802222MYyWHg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-logs": "0.52.1", + "@opentelemetry/sdk-metrics": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-b3": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.25.1.tgz", + "integrity": "sha512-p6HFscpjrv7//kE+7L+3Vn00VEDUJB0n6ZrjkTYHrJ58QZ8B3ajSJhRbCcY6guQ3PDjTbxWklyvIN2ojVbIb1A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.25.1.tgz", + "integrity": "sha512-nBprRf0+jlgxks78G/xq72PipVK+4or9Ypntw0gVZYNTCSK8rg5SeaGV19tV920CMqBD/9UIOiFr23Li/Q8tiA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.25.1.tgz", + "integrity": "sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.52.1.tgz", + "integrity": "sha512-MBYh+WcPPsN8YpRHRmK1Hsca9pVlyyKd4BxOC4SsgHACnl/bPp4Cri9hWhVm5+2tiQ9Zf4qSc1Jshw9tOLGWQA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.25.1.tgz", + "integrity": "sha512-9Mb7q5ioFL4E4dDrc4wC/A3NTHDat44v4I3p2pLPSxRvqUbDIQyMVr9uK+EU69+HWhlET1VaSrRzwdckWqY15Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "lodash.merge": "^4.6.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-node": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.52.1.tgz", + "integrity": "sha512-uEG+gtEr6eKd8CVWeKMhH2olcCHM9dEK68pe0qE0be32BcCRsvYURhHaD1Srngh1SQcnQzZ4TP324euxqtBOJA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/exporter-trace-otlp-grpc": "0.52.1", + "@opentelemetry/exporter-trace-otlp-http": "0.52.1", + "@opentelemetry/exporter-trace-otlp-proto": "0.52.1", + "@opentelemetry/exporter-zipkin": "1.25.1", + "@opentelemetry/instrumentation": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-logs": "0.52.1", + "@opentelemetry/sdk-metrics": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "@opentelemetry/sdk-trace-node": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz", + "integrity": "sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.25.1.tgz", + "integrity": "sha512-nMcjFIKxnFqoez4gUmihdBrbpsEnAX/Xj16sGvZm+guceYE0NE00vLhpDVK6f3q8Q4VFI5xG8JjlXKMB/SkTTQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/context-async-hooks": "1.25.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/propagator-b3": "1.25.1", + "@opentelemetry/propagator-jaeger": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", + "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@paralleldrive/cuid2": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", @@ -4223,12 +4822,110 @@ "@noble/hashes": "^1.1.5" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause", + "optional": true + }, "node_modules/@sec-ant/readable-stream": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "license": "MIT" }, + "node_modules/@selderee/plugin-htmlparser2": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", + "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "domhandler": "^5.0.3", + "selderee": "^0.11.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -4269,12 +4966,12 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.3.tgz", - "integrity": "sha512-AqXFf6DXnuRBXy4SoK/n1mfgHaKaq36bmkphmD1KO0nHq6xK/g9KHSW4HEsPQUBCGdIEfuJifGHwxFXPIFay9Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", + "integrity": "sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4282,15 +4979,15 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.3.tgz", - "integrity": "sha512-N5e7ofiyYDmHxnPnqF8L4KtsbSDwyxFRfDK9bp1d9OyPO4ytRLd0/XxCqi5xVaaqB65v4woW8uey6jND6zxzxQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz", + "integrity": "sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.2", - "@smithy/types": "^4.3.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.3", + "@smithy/util-middleware": "^4.0.4", "tslib": "^2.6.2" }, "engines": { @@ -4298,17 +4995,18 @@ } }, "node_modules/@smithy/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.4.0.tgz", - "integrity": "sha512-dDYISQo7k0Ml/rXlFIjkTmTcQze/LxhtIRAEmZ6HJ/EI0inVxVEVnrUXJ7jPx6ZP0GHUhFm40iQcCgS5apXIXA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.6.0.tgz", + "integrity": "sha512-Pgvfb+TQ4wUNLyHzvgCP4aYZMh16y7GcfF59oirRHcgGgkH1e/s9C0nv/v3WP+Quymyr5je71HeFQCwh+44XLg==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.0.6", - "@smithy/protocol-http": "^5.1.1", - "@smithy/types": "^4.3.0", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.3", - "@smithy/util-stream": "^4.2.1", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-stream": "^4.2.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -4317,15 +5015,15 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.5.tgz", - "integrity": "sha512-saEAGwrIlkb9XxX/m5S5hOtzjoJPEK6Qw2f9pYTbIsMPOFyGSXBBTw95WbOyru8A1vIS2jVCCU1Qhz50QWG3IA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz", + "integrity": "sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.2", - "@smithy/property-provider": "^4.0.3", - "@smithy/types": "^4.3.0", - "@smithy/url-parser": "^4.0.3", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "tslib": "^2.6.2" }, "engines": { @@ -4333,13 +5031,13 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.3.tgz", - "integrity": "sha512-V22KIPXZsE2mc4zEgYGANM/7UbL9jWlOACEolyGyMuTY+jjHJ2PQ0FdopOTS1CS7u6PlAkALmypkv2oQ4aftcg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.4.tgz", + "integrity": "sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "@smithy/util-hex-encoding": "^4.0.0", "tslib": "^2.6.2" }, @@ -4348,14 +5046,14 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.3.tgz", - "integrity": "sha512-yBZwavI31roqTndNI7ONHqesfH01JmjJK6L3uUpZAhyAmr86LN5QiPzfyZGIxQmed8VEK2NRSQT3/JX5V1njfQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.4.tgz", + "integrity": "sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.1", - "@smithy/querystring-builder": "^4.0.3", - "@smithy/types": "^4.3.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/querystring-builder": "^4.0.4", + "@smithy/types": "^4.3.1", "@smithy/util-base64": "^4.0.0", "tslib": "^2.6.2" }, @@ -4364,12 +5062,12 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.3.tgz", - "integrity": "sha512-W5Uhy6v/aYrgtjh9y0YP332gIQcwccQ+EcfWhllL0B9rPae42JngTTUpb8W6wuxaNFzqps4xq5klHckSSOy5fw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz", + "integrity": "sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -4379,12 +5077,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.3.tgz", - "integrity": "sha512-1Bo8Ur1ZGqxvwTqBmv6DZEn0rXtwJGeqiiO2/JFcCtz3nBakOqeXbJBElXJMMzd0ghe8+eB6Dkw98nMYctgizg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz", + "integrity": "sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4404,13 +5102,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.3.tgz", - "integrity": "sha512-NE/Zph4BP5u16bzYq2csq9qD0T6UBLeg4AuNrwNJ7Gv9uLYaGEgelZUOdRndGdMGcUfSGvNlXGb2aA2hPCwJ6g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz", + "integrity": "sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.1", - "@smithy/types": "^4.3.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4418,18 +5116,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.7.tgz", - "integrity": "sha512-KDzM7Iajo6K7eIWNNtukykRT4eWwlHjCEsULZUaSfi/SRSBK8BPRqG5FsVfp58lUxcvre8GT8AIPIqndA0ERKw==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.13.tgz", + "integrity": "sha512-xg3EHV/Q5ZdAO5b0UiIMj3RIOCobuS40pBBODguUDVdko6YK6QIzCVRrHTogVuEKglBWqWenRnZ71iZnLL3ZAQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.4.0", - "@smithy/middleware-serde": "^4.0.6", - "@smithy/node-config-provider": "^4.1.2", - "@smithy/shared-ini-file-loader": "^4.0.3", - "@smithy/types": "^4.3.0", - "@smithy/url-parser": "^4.0.3", - "@smithy/util-middleware": "^4.0.3", + "@smithy/core": "^3.6.0", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", + "@smithy/util-middleware": "^4.0.4", "tslib": "^2.6.2" }, "engines": { @@ -4437,18 +5135,18 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.8.tgz", - "integrity": "sha512-e2OtQgFzzlSG0uCjcJmi02QuFSRTrpT11Eh2EcqqDFy7DYriteHZJkkf+4AsxsrGDugAtPFcWBz1aq06sSX5fQ==", + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.14.tgz", + "integrity": "sha512-eoXaLlDGpKvdmvt+YBfRXE7HmIEtFF+DJCbTPwuLunP0YUnrydl+C4tS+vEM0+nyxXrX3PSUFqC+lP1+EHB1Tw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.2", - "@smithy/protocol-http": "^5.1.1", - "@smithy/service-error-classification": "^4.0.4", - "@smithy/smithy-client": "^4.3.0", - "@smithy/types": "^4.3.0", - "@smithy/util-middleware": "^4.0.3", - "@smithy/util-retry": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/protocol-http": "^5.1.2", + "@smithy/service-error-classification": "^4.0.6", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", "tslib": "^2.6.2", "uuid": "^9.0.1" }, @@ -4470,13 +5168,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.6.tgz", - "integrity": "sha512-YECyl7uNII+jCr/9qEmCu8xYL79cU0fqjo0qxpcVIU18dAPHam/iYwcknAu4Jiyw1uN+sAx7/SMf/Kmef/Jjsg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz", + "integrity": "sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.1", - "@smithy/types": "^4.3.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4484,12 +5182,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.3.tgz", - "integrity": "sha512-baeV7t4jQfQtFxBADFmnhmqBmqR38dNU5cvEgHcMK/Kp3D3bEI0CouoX2Sr/rGuntR+Eg0IjXdxnGGTc6SbIkw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz", + "integrity": "sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4497,14 +5195,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.2.tgz", - "integrity": "sha512-SUvNup8iU1v7fmM8XPk+27m36udmGCfSz+VZP5Gb0aJ3Ne0X28K/25gnsrg3X1rWlhcnhzNUUysKW/Ied46ivQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz", + "integrity": "sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.3", - "@smithy/shared-ini-file-loader": "^4.0.3", - "@smithy/types": "^4.3.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4512,15 +5210,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.5.tgz", - "integrity": "sha512-T7QglZC1vS7SPT44/1qSIAQEx5bFKb3LfO6zw/o4Xzt1eC5HNoH1TkS4lMYA9cWFbacUhx4hRl/blLun4EOCkg==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.6.tgz", + "integrity": "sha512-NqbmSz7AW2rvw4kXhKGrYTiJVDHnMsFnX4i+/FzcZAfbOBauPYs2ekuECkSbtqaxETLLTu9Rl/ex6+I2BKErPA==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.3", - "@smithy/protocol-http": "^5.1.1", - "@smithy/querystring-builder": "^4.0.3", - "@smithy/types": "^4.3.0", + "@smithy/abort-controller": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/querystring-builder": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4528,12 +5226,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.3.tgz", - "integrity": "sha512-Wcn17QNdawJZcZZPBuMuzyBENVi1AXl4TdE0jvzo4vWX2x5df/oMlmr/9M5XAAC6+yae4kWZlOYIsNsgDrMU9A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz", + "integrity": "sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4541,12 +5239,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.1.tgz", - "integrity": "sha512-Vsay2mzq05DwNi9jK01yCFtfvu9HimmgC7a4HTs7lhX12Sx8aWsH0mfz6q/02yspSp+lOB+Q2HJwi4IV2GKz7A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz", + "integrity": "sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4554,12 +5252,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.3.tgz", - "integrity": "sha512-UUzIWMVfPmDZcOutk2/r1vURZqavvQW0OHvgsyNV0cKupChvqg+/NKPRMaMEe+i8tP96IthMFeZOZWpV+E4RAw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz", + "integrity": "sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" }, @@ -4568,12 +5266,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.3.tgz", - "integrity": "sha512-K5M4ZJQpFCblOJ5Oyw7diICpFg1qhhR47m2/5Ef1PhGE19RaIZf50tjYFrxa6usqcuXyTiFPGo4d1geZdH4YcQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz", + "integrity": "sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4581,24 +5279,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.4.tgz", - "integrity": "sha512-W5ScbQ1bTzgH91kNEE2CvOzM4gXlDOqdow4m8vMFSIXCel2scbHwjflpVNnC60Y3F1m5i7w2gQg9lSnR+JsJAA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.6.tgz", + "integrity": "sha512-RRoTDL//7xi4tn5FrN2NzH17jbgmnKidUqd4KvquT0954/i6CXXkh1884jBiunq24g9cGtPBEXlU40W6EpNOOg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0" + "@smithy/types": "^4.3.1" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.3.tgz", - "integrity": "sha512-vHwlrqhZGIoLwaH8vvIjpHnloShqdJ7SUPNM2EQtEox+yEDFTVQ7E+DLZ+6OhnYEgFUwPByJyz6UZaOu2tny6A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz", + "integrity": "sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4606,16 +5304,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.1.tgz", - "integrity": "sha512-zy8Repr5zvT0ja+Tf5wjV/Ba6vRrhdiDcp/ww6cvqYbSEudIkziDe3uppNRlFoCViyJXdPnLcwyZdDLA4CHzSg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz", + "integrity": "sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.1.1", - "@smithy/types": "^4.3.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.3", + "@smithy/util-middleware": "^4.0.4", "@smithy/util-uri-escape": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -4625,17 +5323,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.3.0.tgz", - "integrity": "sha512-DNsRA38pN6tYHUjebmwD9e4KcgqTLldYQb2gC6K+oxXYdCTxPn6wV9+FvOa6wrU2FQEnGJoi+3GULzOTKck/tg==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.5.tgz", + "integrity": "sha512-+lynZjGuUFJaMdDYSTMnP/uPBBXXukVfrJlP+1U/Dp5SFTEI++w6NMga8DjOENxecOF71V9Z2DllaVDYRnGlkg==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.4.0", - "@smithy/middleware-endpoint": "^4.1.7", - "@smithy/middleware-stack": "^4.0.3", - "@smithy/protocol-http": "^5.1.1", - "@smithy/types": "^4.3.0", - "@smithy/util-stream": "^4.2.1", + "@smithy/core": "^3.6.0", + "@smithy/middleware-endpoint": "^4.1.13", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-stream": "^4.2.2", "tslib": "^2.6.2" }, "engines": { @@ -4643,9 +5341,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.0.tgz", - "integrity": "sha512-+1iaIQHthDh9yaLhRzaoQxRk+l9xlk+JjMFxGRhNLz+m9vKOkjNeU8QuB4w3xvzHyVR/BVlp/4AXDHjoRIkfgQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz", + "integrity": "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -4655,13 +5353,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.3.tgz", - "integrity": "sha512-n5/DnosDu/tweOqUUNtUbu7eRIR4J/Wz9nL7V5kFYQQVb8VYdj7a4G5NJHCw6o21ul7CvZoJkOpdTnsQDLT0tQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz", + "integrity": "sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.0.3", - "@smithy/types": "^4.3.0", + "@smithy/querystring-parser": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4732,14 +5430,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.15.tgz", - "integrity": "sha512-bJJ/B8owQbHAflatSq92f9OcV8858DJBQF1Y3GRjB8psLyUjbISywszYPFw16beREHO/C3I3taW4VGH+tOuwrQ==", + "version": "4.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.21.tgz", + "integrity": "sha512-wM0jhTytgXu3wzJoIqpbBAG5U6BwiubZ6QKzSbP7/VbmF1v96xlAbX2Am/mz0Zep0NLvLh84JT0tuZnk3wmYQA==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.3", - "@smithy/smithy-client": "^4.3.0", - "@smithy/types": "^4.3.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", "bowser": "^2.11.0", "tslib": "^2.6.2" }, @@ -4748,17 +5446,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.15.tgz", - "integrity": "sha512-8CUrEW2Ni5q+NmYkj8wsgkfqoP7l4ZquptFbq92yQE66xevc4SxqP2zH6tMtN158kgBqBDsZ+qlrRwXWOjCR8A==", + "version": "4.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.21.tgz", + "integrity": "sha512-/F34zkoU0GzpUgLJydHY8Rxu9lBn8xQC/s/0M0U9lLBkYbA1htaAFjWYJzpzsbXPuri5D1H8gjp2jBum05qBrA==", "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^4.1.3", - "@smithy/credential-provider-imds": "^4.0.5", - "@smithy/node-config-provider": "^4.1.2", - "@smithy/property-provider": "^4.0.3", - "@smithy/smithy-client": "^4.3.0", - "@smithy/types": "^4.3.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/smithy-client": "^4.4.5", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4766,13 +5464,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.5.tgz", - "integrity": "sha512-PjDpqLk24/vAl340tmtCA++Q01GRRNH9cwL9qh46NspAX9S+IQVcK+GOzPt0GLJ6KYGyn8uOgo2kvJhiThclJw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz", + "integrity": "sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.2", - "@smithy/types": "^4.3.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4792,12 +5490,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.3.tgz", - "integrity": "sha512-iIsC6qZXxkD7V3BzTw3b1uK8RVC1M8WvwNxK1PKrH9FnxntCd30CSunXjL/8iJBE8Z0J14r2P69njwIpRG4FBQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz", + "integrity": "sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.0", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4805,13 +5503,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.4.tgz", - "integrity": "sha512-Aoqr9W2jDYGrI6OxljN8VmLDQIGO4VdMAUKMf9RGqLG8hn6or+K41NEy1Y5dtum9q8F7e0obYAuKl2mt/GnpZg==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.6.tgz", + "integrity": "sha512-+YekoF2CaSMv6zKrA6iI/N9yva3Gzn4L6n35Luydweu5MMPYpiGZlWqehPHDHyNbnyaYlz/WJyYAZnC+loBDZg==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.0.4", - "@smithy/types": "^4.3.0", + "@smithy/service-error-classification": "^4.0.6", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -4819,14 +5517,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.1.tgz", - "integrity": "sha512-W3IR0x5DY6iVtjj5p902oNhD+Bz7vs5S+p6tppbPa509rV9BdeXZjGuRSCtVEad9FA0Mba+tNUtUmtnSI1nwUw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.2.tgz", + "integrity": "sha512-aI+GLi7MJoVxg24/3J1ipwLoYzgkB4kUfogZfnslcYlynj3xsQ0e7vk4TnTro9hhsS5PvX1mwmkRqqHQjwcU7w==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.0.3", - "@smithy/node-http-handler": "^4.0.5", - "@smithy/types": "^4.3.0", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/types": "^4.3.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-hex-encoding": "^4.0.0", @@ -4886,6 +5584,29 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/@tokenizer/inflate/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@tokenizer/inflate/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/@tokenizer/token": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", @@ -4907,9 +5628,9 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "license": "MIT", "dependencies": { @@ -4928,9 +5649,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", "dev": true, "license": "MIT", "dependencies": { @@ -4943,6 +5664,17 @@ "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", "license": "MIT" }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -4953,6 +5685,13 @@ "@types/node": "*" } }, + "node_modules/@types/html-to-text": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-9.0.4.tgz", + "integrity": "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ==", + "license": "MIT", + "optional": true + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -4991,10 +5730,17 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "license": "MIT", + "optional": true + }, "node_modules/@types/node": { - "version": "18.19.81", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.81.tgz", - "integrity": "sha512-7KO9oZ2//ivtSsryp0LQUqq79zyGXzwq1WqfywpC9ucjY7YyltMMmxWgtRFRKCxwa7VPxVBVy4kHf5UC1E8Lug==", + "version": "18.19.113", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.113.tgz", + "integrity": "sha512-TmSTE9vyebJ9vSEiU+P+0Sp4F5tMgjiEOZaQUW6wA3ODvi6uBgkHQ+EsIu0pbiKvf9QHEvyRCiaz03rV0b+IaA==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -5010,6 +5756,13 @@ "form-data": "^4.0.0" } }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT", + "optional": true + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -5065,6 +5818,29 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "optional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "optional": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/agent-base": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", @@ -5087,15 +5863,15 @@ } }, "node_modules/ai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/ai/-/ai-4.3.10.tgz", - "integrity": "sha512-jw+ahNu+T4SHj9gtraIKtYhanJI6gj2IZ5BFcfEHgoyQVMln5a5beGjzl/nQSX6FxyLqJ/UBpClRa279EEKK/Q==", + "version": "4.3.16", + "resolved": "https://registry.npmjs.org/ai/-/ai-4.3.16.tgz", + "integrity": "sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "1.1.3", - "@ai-sdk/provider-utils": "2.2.7", - "@ai-sdk/react": "1.2.9", - "@ai-sdk/ui-utils": "1.2.8", + "@ai-sdk/provider-utils": "2.2.8", + "@ai-sdk/react": "1.2.12", + "@ai-sdk/ui-utils": "1.2.11", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, @@ -5112,6 +5888,28 @@ } } }, + "node_modules/ai-sdk-provider-gemini-cli": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/ai-sdk-provider-gemini-cli/-/ai-sdk-provider-gemini-cli-0.0.3.tgz", + "integrity": "sha512-gryNbArgNC2kqWlCsSlheZOCoowYlEfLWZZYac5kwDVG65P00hAaqiUNsBHLVPtDrqtE4rQZDj2zwhBuAwfwYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@ai-sdk/provider": "^1.1.3", + "@ai-sdk/provider-utils": "^2.2.8", + "@google/gemini-cli-core": "^0.1.4", + "@google/genai": "^1.7.0", + "google-auth-library": "^9.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.23.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.23.8" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5152,6 +5950,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-align/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -5203,18 +6010,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", @@ -5228,15 +6023,12 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -5342,6 +6134,22 @@ "@babel/core": "^7.8.0" } }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/babel-jest/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -5393,6 +6201,16 @@ "node": ">=8" } }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/babel-plugin-jest-hoist": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", @@ -5457,7 +6275,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/base64-js": { @@ -5526,34 +6344,19 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "license": "MIT", "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, "node_modules/bowser": { @@ -5584,22 +6387,50 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, + "node_modules/boxen/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -5609,9 +6440,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -5629,10 +6460,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -5664,6 +6495,22 @@ "dev": true, "license": "MIT" }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -5725,9 +6572,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001707", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", - "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", "dev": true, "funding": [ { @@ -5793,7 +6640,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/cli-boxes": { @@ -5809,15 +6656,16 @@ } }, "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5853,6 +6701,21 @@ "node": ">=8" } }, + "node_modules/cli-highlight/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/cli-highlight/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -5886,6 +6749,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/cli-highlight/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cli-highlight/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -5998,6 +6870,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cli-table3/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6041,32 +6922,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-truncate/node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -6116,12 +6971,36 @@ "node": ">=8" } }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cliui/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6347,6 +7226,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/create-jest/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6386,20 +7281,12 @@ "license": "BSD-3-Clause" }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "ms": "2.0.0" } }, "node_modules/decimal.js": { @@ -6409,9 +7296,9 @@ "license": "MIT" }, "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6427,12 +7314,55 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "license": "MIT", + "optional": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -6501,6 +7431,16 @@ "wrappy": "1" } }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-match-patch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", @@ -6530,10 +7470,69 @@ "node": ">=8" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "optional": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -6556,6 +7555,13 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT", + "optional": true + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -6572,9 +7578,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.123", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", - "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", + "version": "1.5.178", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.178.tgz", + "integrity": "sha512-wObbz/ar3Bc6e4X5vf0iO8xTN8YAjN/tgiAOJLr7yjYFtP9wAjq8Mb5h0yn6kResir+VYx2DXBj9NNobs0ETSA==", "dev": true, "license": "ISC" }, @@ -6643,6 +7649,19 @@ "node": ">=8" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "optional": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/environment": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", @@ -6712,9 +7731,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.36.0.tgz", - "integrity": "sha512-5lpkRpDELuTSeAL//Rcg5urg+K/yOD1BobJSiNeCc89snMqgrhckmj8jdljqraDbpREiXTNW311RN518eVHBng==", + "version": "1.39.5", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.5.tgz", + "integrity": "sha512-z9V0qU4lx1TBXDNFWfAASWk6RNU6c6+TJBKE+FLIg8u0XJ6Yw58Hi0yX8ftEouj6p1QARRlXLFfHbIli93BdQQ==", "dev": true, "license": "MIT", "workspaces": [ @@ -6723,9 +7742,9 @@ ] }, "node_modules/esbuild": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", - "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -6736,31 +7755,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.3", - "@esbuild/android-arm": "0.25.3", - "@esbuild/android-arm64": "0.25.3", - "@esbuild/android-x64": "0.25.3", - "@esbuild/darwin-arm64": "0.25.3", - "@esbuild/darwin-x64": "0.25.3", - "@esbuild/freebsd-arm64": "0.25.3", - "@esbuild/freebsd-x64": "0.25.3", - "@esbuild/linux-arm": "0.25.3", - "@esbuild/linux-arm64": "0.25.3", - "@esbuild/linux-ia32": "0.25.3", - "@esbuild/linux-loong64": "0.25.3", - "@esbuild/linux-mips64el": "0.25.3", - "@esbuild/linux-ppc64": "0.25.3", - "@esbuild/linux-riscv64": "0.25.3", - "@esbuild/linux-s390x": "0.25.3", - "@esbuild/linux-x64": "0.25.3", - "@esbuild/netbsd-arm64": "0.25.3", - "@esbuild/netbsd-x64": "0.25.3", - "@esbuild/openbsd-arm64": "0.25.3", - "@esbuild/openbsd-x64": "0.25.3", - "@esbuild/sunos-x64": "0.25.3", - "@esbuild/win32-arm64": "0.25.3", - "@esbuild/win32-ia32": "0.25.3", - "@esbuild/win32-x64": "0.25.3" + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" } }, "node_modules/escalade": { @@ -6833,12 +7852,12 @@ } }, "node_modules/eventsource-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", - "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.3.tgz", + "integrity": "sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA==", "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/execa": { @@ -6865,22 +7884,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -6954,9 +7957,9 @@ } }, "node_modules/express-rate-limit": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", - "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", "license": "MIT", "engines": { "node": ">= 16" @@ -6965,37 +7968,7 @@ "url": "https://github.com/sponsors/express-rate-limit" }, "peerDependencies": { - "express": "^4.11 || 5 || ^5.0.0-beta.1" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/express/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "express": ">= 4.11" } }, "node_modules/extend": { @@ -7224,6 +8197,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fastmcp/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/fastmcp/node_modules/yargs": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", @@ -7277,9 +8267,9 @@ "license": "MIT" }, "node_modules/figlet": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.0.tgz", - "integrity": "sha512-chzvGjd+Sp7KUvPHZv6EXV5Ir3Q7kYNpCr4aHrRW79qFtTefmQZNny+W1pW9kf5zeE6dikku2W50W/wAH2xWgw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.1.tgz", + "integrity": "sha512-kEC3Sme+YvA8Hkibv0NR1oClGcWia0VB2fC1SlMy027cwe795Xx40Xiv/nw/iFAwQLupymWh+uhAAErn/7hwPg==", "license": "MIT", "bin": { "figlet": "bin/index.js" @@ -7325,7 +8315,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -7352,21 +8342,6 @@ "node": ">= 0.8" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7381,15 +8356,33 @@ "node": ">=8" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "optional": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -7534,26 +8527,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gaxios/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/gaxios/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -7673,9 +8646,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7686,22 +8659,21 @@ } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "license": "ISC", + "optional": true, "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" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "*" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -7751,6 +8723,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globby/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/google-auth-library": { "version": "9.15.1", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", @@ -7768,27 +8750,6 @@ "node": ">=14" } }, - "node_modules/google-auth-library/node_modules/jwa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", - "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/google-auth-library/node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, "node_modules/google-logging-utils": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", @@ -7854,27 +8815,6 @@ "node": ">=14.0.0" } }, - "node_modules/gtoken/node_modules/jwa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", - "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/gtoken/node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -7948,6 +8888,43 @@ "dev": true, "license": "MIT" }, + "node_modules/html-to-text": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", + "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@selderee/plugin-htmlparser2": "^0.11.0", + "deepmerge": "^4.3.1", + "dom-serializer": "^2.0.0", + "htmlparser2": "^8.0.2", + "selderee": "^0.11.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -7977,6 +8954,29 @@ "node": ">= 14" } }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/human-id": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.1.1.tgz", @@ -8039,15 +9039,28 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 4" } }, + "node_modules/import-in-the-middle": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.14.2.tgz", + "integrity": "sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -8110,9 +9123,9 @@ "license": "ISC" }, "node_modules/ink": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ink/-/ink-5.2.0.tgz", - "integrity": "sha512-gHzSBBvsh/1ZYuGi+aKzU7RwnYIr6PSz56or9T90i4DDS99euhN7nYKOMR3OTev0dKIB6Zod3vSapYzqoilQcg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ink/-/ink-5.2.1.tgz", + "integrity": "sha512-BqcUyWrG9zq5HIwW6JcfFHsIYebJkWWb4fczNah1goUO0vv5vneIlfwuS85twyJ5hYR/y18FlAYUxrO9ChIWVg==", "dev": true, "license": "MIT", "dependencies": { @@ -8174,78 +9187,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ink/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ink/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ink/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ink/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ink/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ink/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -8253,15 +9194,46 @@ "dev": true, "license": "ISC" }, - "node_modules/inquirer": { - "version": "12.5.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.5.0.tgz", - "integrity": "sha512-aiBBq5aKF1k87MTxXDylLfwpRwToShiHrSv4EmB07EYyLgmnjEz5B3rn0aGw1X3JA/64Ngf2T54oGwc+BCsPIQ==", + "node_modules/ink/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.9", - "@inquirer/prompts": "^7.4.0", - "@inquirer/type": "^3.0.5", + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/inquirer": { + "version": "12.6.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.6.3.tgz", + "integrity": "sha512-eX9beYAjr1MqYsIjx1vAheXsRk1jbZRvHLcBu5nA9wX0rXR1IfCZLnVLp4Ym4mrhqmh7AuANwcdtgQ291fZDfQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.13", + "@inquirer/prompts": "^7.5.3", + "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2", "mute-stream": "^2.0.0", "run-async": "^3.0.0", @@ -8299,7 +9271,7 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -8311,6 +9283,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "optional": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -8322,12 +9310,16 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-generator-fn": { @@ -8369,6 +9361,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-interactive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", @@ -8385,7 +9396,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -8457,6 +9468,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -8490,19 +9517,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", @@ -8533,6 +9547,31 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -8547,6 +9586,22 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -8688,6 +9743,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jest-changed-files/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -8737,6 +9808,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-circus/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -8754,6 +9841,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jest-cli": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", @@ -8788,6 +9891,22 @@ } } }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-cli/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -8851,6 +9970,33 @@ } } }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/jest-config/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -8868,6 +10014,41 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "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": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -8884,6 +10065,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-diff/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -8931,6 +10128,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-each/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9032,6 +10245,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-matcher-utils/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9070,6 +10299,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-message-util/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9165,6 +10410,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-resolve/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9215,6 +10476,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-runner/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9232,6 +10509,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jest-runtime": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", @@ -9266,6 +10559,33 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/jest-runtime/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9283,6 +10603,41 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "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": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -9315,6 +10670,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-snapshot/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9332,19 +10703,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -9363,6 +10721,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-util/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9398,6 +10772,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-validate/node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -9448,6 +10838,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/jest-watcher/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9580,6 +10986,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, "node_modules/jsondiffpatch": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.6.0.tgz", @@ -9629,30 +11041,18 @@ "npm": ">=6" } }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", "license": "MIT", "dependencies": { - "buffer-equal-constant-time": "1.0.1", + "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, - "node_modules/jws": { + "node_modules/jsonwebtoken/node_modules/jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", @@ -9662,6 +11062,33 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "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.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -9672,6 +11099,16 @@ "node": ">=6" } }, + "node_modules/leac": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", + "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==", + "license": "MIT", + "optional": true, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -9702,6 +11139,13 @@ "node": ">=8" } }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT", + "optional": true + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -9738,6 +11182,13 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT", + "optional": true + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -9779,6 +11230,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0", + "optional": true + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -9813,19 +11271,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -9919,7 +11364,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -9930,16 +11375,15 @@ } }, "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "license": "MIT", "bin": { "mime": "cli.js" }, "engines": { - "node": ">=4.0.0" + "node": ">=4" } }, "node_modules/mime-db": { @@ -9989,16 +11433,29 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "license": "ISC", + "optional": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=16 || 14 >=14.17" } }, "node_modules/mock-fs": { @@ -10011,6 +11468,13 @@ "node": ">=12.0.0" } }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT", + "optional": true + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -10022,9 +11486,9 @@ } }, "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/mute-stream": { @@ -10085,6 +11549,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", "funding": [ { "type": "github", @@ -10100,6 +11565,26 @@ "node": ">=10.5.0" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -10218,12 +11703,32 @@ } }, "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, "license": "MIT", "dependencies": { - "mimic-function": "^5.0.0" + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", + "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", + "license": "MIT", + "optional": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, "engines": { "node": ">=18" @@ -10233,9 +11738,9 @@ } }, "node_modules/openai": { - "version": "4.89.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.89.0.tgz", - "integrity": "sha512-XNI0q2l8/Os6jmojxaID5EhyQjxZgzR2gWcpEjYWK5hGKwE7AcifxEY7UNwFDDHJQXqeiosQ0CJwQN+rvnwdjA==", + "version": "4.104.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz", + "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==", "license": "Apache-2.0", "dependencies": { "@types/node": "^18.11.18", @@ -10271,26 +11776,6 @@ "js-tiktoken": "^1.0.7" } }, - "node_modules/openai/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/ora": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", @@ -10314,6 +11799,52 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -10344,16 +11875,16 @@ } }, "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10372,22 +11903,6 @@ "node": ">=8" } }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-map": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", @@ -10408,6 +11923,13 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0", + "optional": true + }, "node_modules/package-manager-detector": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", @@ -10470,6 +11992,20 @@ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "license": "MIT" }, + "node_modules/parseley": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", + "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", + "license": "MIT", + "optional": true, + "dependencies": { + "leac": "^0.6.0", + "peberminta": "^0.9.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -10528,9 +12064,26 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, + "devOptional": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -10547,6 +12100,16 @@ "node": ">=8" } }, + "node_modules/peberminta": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", + "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==", + "license": "MIT", + "optional": true, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -10558,7 +12121,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -10578,9 +12141,9 @@ } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, "license": "MIT", "engines": { @@ -10610,9 +12173,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -10682,6 +12245,31 @@ "node": ">= 6" } }, + "node_modules/protobufjs": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz", + "integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -10722,12 +12310,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -10784,20 +12372,32 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", - "iconv-lite": "0.4.24", + "iconv-lite": "0.6.3", "unpipe": "1.0.0" }, "engines": { "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -10860,13 +12460,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "license": "MIT" - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -10876,11 +12469,51 @@ "node": ">=0.10.0" } }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/require-in-the-middle/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/require-in-the-middle/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -10941,21 +12574,55 @@ } }, "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, "license": "MIT", "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -10983,6 +12650,29 @@ "node": ">= 18" } }, + "node_modules/router/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/router/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/router/node_modules/path-to-regexp": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", @@ -10992,6 +12682,19 @@ "node": ">=16" } }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-async": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", @@ -11076,14 +12779,29 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", "license": "BSD-3-Clause" }, + "node_modules/selderee": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", + "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", + "license": "MIT", + "optional": true, + "dependencies": { + "parseley": "^0.12.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { @@ -11110,21 +12828,6 @@ "node": ">= 0.8.0" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -11134,17 +12837,11 @@ "node": ">= 0.8" } }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { "version": "1.16.2", @@ -11188,6 +12885,26 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause", + "optional": true + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -11272,6 +12989,47 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-git": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.28.0.tgz", + "integrity": "sha512-Rs/vQRwsn1ILH1oBUy8NucJlXmnnLeLCfcvbSehkPzbv3wwoFWIdtfd6Ndo6ZPhlPsCZ60CPI4rxurnwAa+a2w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/simple-git/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/simple-git/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -11306,19 +13064,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", @@ -11468,6 +13213,62 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", @@ -11483,6 +13284,30 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -11548,9 +13373,9 @@ } }, "node_modules/superagent": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", - "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.1.tgz", + "integrity": "sha512-O+PCv11lgTNJUzy49teNAWLjBZfc+A1enOwTpLlH6/rsvKcTwcdTT8m9azGkVqM7HBl5jpyZ7KTPhHweokBcdg==", "dev": true, "license": "MIT", "dependencies": { @@ -11559,7 +13384,7 @@ "debug": "^4.3.4", "fast-safe-stringify": "^2.1.1", "form-data": "^4.0.0", - "formidable": "^3.5.1", + "formidable": "^3.5.4", "methods": "^1.1.2", "mime": "2.6.0", "qs": "^6.11.0" @@ -11568,15 +13393,53 @@ "node": ">=14.18.0" } }, + "node_modules/superagent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/supertest": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.0.tgz", - "integrity": "sha512-5QeSO8hSrKghtcWEoPiO036fxH0Ii2wVQfFZSP0oqQhmjk8bOLhDFXr4JrvaFmPuEWUoq4znY3uSi8UzLKxGqw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.1.tgz", + "integrity": "sha512-aI59HBTlG9e2wTjxGJV+DygfNLgnWbGdZxiA/sgrnNNikIW8lbDvCtF6RnhZoJ82nU7qv7ZLjrvWqCEm52fAmw==", "dev": true, "license": "MIT", "dependencies": { "methods": "^1.1.2", - "superagent": "^9.0.1" + "superagent": "^10.2.1" }, "engines": { "node": ">=14.18.0" @@ -11598,7 +13461,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -11648,6 +13511,52 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "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": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -11720,7 +13629,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -11739,9 +13648,9 @@ } }, "node_modules/token-types": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.0.tgz", - "integrity": "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.3.tgz", + "integrity": "sha512-IKJ6EzuPPWtKtEIEPpIdXv9j5j2LGJEYk0CKY2efgKoYKLBiZdh6iQkLVBow/CB3phyWAWCyk+bZeaimJn6uRQ==", "license": "MIT", "dependencies": { "@tokenizer/token": "^0.3.0", @@ -11774,9 +13683,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", + "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11804,12 +13713,12 @@ } }, "node_modules/type-fest": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.37.0.tgz", - "integrity": "sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=16" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11841,9 +13750,9 @@ } }, "node_modules/undici": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.10.0.tgz", - "integrity": "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.11.0.tgz", + "integrity": "sha512-heTSIac3iLhsmZhUCjyS3JQEkZELateufzZuBaVM5RHXdSBMb1LPMQf5x+FH7qjsZYDP0ttAc3nnVpUB+wYbOg==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -12059,34 +13968,174 @@ } }, "node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", + "optional": true, "engines": { - "node": ">=12" + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -12115,9 +14164,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "devOptional": true, "license": "MIT", "engines": { @@ -12228,6 +14277,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/yargs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -12299,22 +14357,22 @@ "license": "MIT" }, "node_modules/zod": { - "version": "3.25.64", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.64.tgz", - "integrity": "sha512-hbP9FpSZf7pkS7hRVUrOjhwKJNyampPgtXKc3AN6DsWtoHsg2Sb4SQaS4Tcay380zSwd2VPo9G9180emBACp5g==", + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-to-json-schema": { - "version": "3.24.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", - "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", "license": "ISC", "peerDependencies": { "zod": "^3.24.1" } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 4e5b1803..18e5e29e 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "gradient-string": "^3.0.0", "helmet": "^8.1.0", "inquirer": "^12.5.0", + "jsonc-parser": "^3.3.1", "jsonwebtoken": "^9.0.2", "lru-cache": "^10.2.0", "ollama-ai-provider": "^1.2.0", @@ -77,7 +78,8 @@ "zod": "^3.23.8" }, "optionalDependencies": { - "@anthropic-ai/claude-code": "^1.0.25" + "@anthropic-ai/claude-code": "^1.0.25", + "ai-sdk-provider-gemini-cli": "^0.0.3" }, "engines": { "node": ">=18.0.0" diff --git a/scripts/init.js b/scripts/init.js index f168429a..10ecb200 100755 --- a/scripts/init.js +++ b/scripts/init.js @@ -30,6 +30,7 @@ import { convertAllRulesToProfileRules, getRulesProfile } from '../src/utils/rule-transformer.js'; +import { updateConfigMaxTokens } from './modules/update-config-tokens.js'; import { execSync } from 'child_process'; import { @@ -623,6 +624,14 @@ function createProjectStructure( } ); + // Update config.json with correct maxTokens values from supported-models.json + const configPath = path.join(targetDir, TASKMASTER_CONFIG_FILE); + if (updateConfigMaxTokens(configPath)) { + log('info', 'Updated config with correct maxTokens values'); + } else { + log('warn', 'Could not update maxTokens in config'); + } + // Copy .gitignore with GitTasks preference try { const gitignoreTemplatePath = path.join( @@ -757,6 +766,44 @@ function createProjectStructure( } // ===================================== + // === Add Response Language Step === + if (!isSilentMode() && !dryRun && !options?.yes) { + console.log( + boxen(chalk.cyan('Configuring Response Language...'), { + padding: 0.5, + margin: { top: 1, bottom: 0.5 }, + borderStyle: 'round', + borderColor: 'blue' + }) + ); + log( + 'info', + 'Running interactive response language setup. Please input your preferred language.' + ); + try { + execSync('npx task-master lang --setup', { + stdio: 'inherit', + cwd: targetDir + }); + log('success', 'Response Language configured.'); + } catch (error) { + log('error', 'Failed to configure response language:', error.message); + log('warn', 'You may need to run "task-master lang --setup" manually.'); + } + } else if (isSilentMode() && !dryRun) { + log( + 'info', + 'Skipping interactive response language setup in silent (MCP) mode.' + ); + log( + 'warn', + 'Please configure response language using "task-master models --set-response-language" or the "models" MCP tool.' + ); + } else if (dryRun) { + log('info', 'DRY RUN: Skipping interactive response language setup.'); + } + // ===================================== + // === Add Model Configuration Step === if (!isSilentMode() && !dryRun && !options?.yes) { console.log( diff --git a/scripts/modules/ai-services-unified.js b/scripts/modules/ai-services-unified.js index ec699565..e8f4f549 100644 --- a/scripts/modules/ai-services-unified.js +++ b/scripts/modules/ai-services-unified.js @@ -15,6 +15,7 @@ import { getFallbackProvider, getFallbackModelId, getParametersForRole, + getResponseLanguage, getUserId, MODEL_MAP, getDebugFlag, @@ -24,7 +25,8 @@ import { getAzureBaseURL, getBedrockBaseURL, getVertexProjectId, - getVertexLocation + getVertexLocation, + providersWithoutApiKeys } from './config-manager.js'; import { log, @@ -45,7 +47,8 @@ import { BedrockAIProvider, AzureProvider, VertexAIProvider, - ClaudeCodeProvider + ClaudeCodeProvider, + GeminiCliProvider } from '../../src/ai-providers/index.js'; // Create provider instances @@ -60,7 +63,8 @@ const PROVIDERS = { bedrock: new BedrockAIProvider(), azure: new AzureProvider(), vertex: new VertexAIProvider(), - 'claude-code': new ClaudeCodeProvider() + 'claude-code': new ClaudeCodeProvider(), + 'gemini-cli': new GeminiCliProvider() }; // Helper function to get cost for a specific model @@ -232,6 +236,12 @@ function _resolveApiKey(providerName, session, projectRoot = null) { return 'claude-code-no-key-required'; } + // Gemini CLI can work without an API key (uses CLI auth) + if (providerName === 'gemini-cli') { + const apiKey = resolveEnvVariable('GEMINI_API_KEY', session, projectRoot); + return apiKey || 'gemini-cli-no-key-required'; + } + const keyMap = { openai: 'OPENAI_API_KEY', anthropic: 'ANTHROPIC_API_KEY', @@ -244,7 +254,8 @@ function _resolveApiKey(providerName, session, projectRoot = null) { ollama: 'OLLAMA_API_KEY', bedrock: 'AWS_ACCESS_KEY_ID', vertex: 'GOOGLE_API_KEY', - 'claude-code': 'CLAUDE_CODE_API_KEY' // Not actually used, but included for consistency + 'claude-code': 'CLAUDE_CODE_API_KEY', // Not actually used, but included for consistency + 'gemini-cli': 'GEMINI_API_KEY' }; const envVarName = keyMap[providerName]; @@ -257,7 +268,7 @@ function _resolveApiKey(providerName, session, projectRoot = null) { const apiKey = resolveEnvVariable(envVarName, session, projectRoot); // Special handling for providers that can use alternative auth - if (providerName === 'ollama' || providerName === 'bedrock') { + if (providersWithoutApiKeys.includes(providerName?.toLowerCase())) { return apiKey || null; } @@ -457,7 +468,7 @@ async function _unifiedServiceRunner(serviceType, params) { } // Check API key if needed - if (providerName?.toLowerCase() !== 'ollama') { + if (!providersWithoutApiKeys.includes(providerName?.toLowerCase())) { if (!isApiKeySet(providerName, session, effectiveProjectRoot)) { log( 'warn', @@ -541,9 +552,12 @@ async function _unifiedServiceRunner(serviceType, params) { } const messages = []; - if (systemPrompt) { - messages.push({ role: 'system', content: systemPrompt }); - } + const responseLanguage = getResponseLanguage(effectiveProjectRoot); + const systemPromptWithLanguage = `${systemPrompt} \n\n Always respond in ${responseLanguage}.`; + messages.push({ + role: 'system', + content: systemPromptWithLanguage.trim() + }); // IN THE FUTURE WHEN DOING CONTEXT IMPROVEMENTS // { diff --git a/scripts/modules/commands.js b/scripts/modules/commands.js index 23e6d1bb..8b653463 100644 --- a/scripts/modules/commands.js +++ b/scripts/modules/commands.js @@ -42,7 +42,8 @@ import { findTaskById, taskExists, moveTask, - migrateProject + migrateProject, + setResponseLanguage } from './task-manager.js'; import { @@ -69,7 +70,9 @@ import { ConfigurationError, isConfigFilePresent, getAvailableModels, - getBaseUrlForRole + getBaseUrlForRole, + getDefaultNumTasks, + getDefaultSubtasks } from './config-manager.js'; import { CUSTOM_PROVIDERS } from '../../src/constants/providers.js'; @@ -803,7 +806,11 @@ function registerCommands(programInstance) { 'Path to the PRD file (alternative to positional argument)' ) .option('-o, --output ', 'Output file path', TASKMASTER_TASKS_FILE) - .option('-n, --num-tasks ', 'Number of tasks to generate', '10') + .option( + '-n, --num-tasks ', + 'Number of tasks to generate', + getDefaultNumTasks() + ) .option('-f, --force', 'Skip confirmation when overwriting existing tasks') .option( '--append', @@ -3421,6 +3428,10 @@ ${result.result} '--vertex', 'Allow setting a custom Vertex AI model ID (use with --set-*) ' ) + .option( + '--gemini-cli', + 'Allow setting a Gemini CLI model ID (use with --set-*)' + ) .addHelpText( 'after', ` @@ -3435,6 +3446,7 @@ Examples: $ task-master models --set-main sonnet --claude-code # Set Claude Code model for main role $ task-master models --set-main gpt-4o --azure # Set custom Azure OpenAI model for main role $ task-master models --set-main claude-3-5-sonnet@20241022 --vertex # Set custom Vertex AI model for main role + $ task-master models --set-main gemini-2.5-pro --gemini-cli # Set Gemini CLI model for main role $ task-master models --setup # Run interactive setup` ) .action(async (options) => { @@ -3448,12 +3460,13 @@ Examples: options.openrouter, options.ollama, options.bedrock, - options.claudeCode + options.claudeCode, + options.geminiCli ].filter(Boolean).length; if (providerFlags > 1) { console.error( chalk.red( - 'Error: Cannot use multiple provider flags (--openrouter, --ollama, --bedrock, --claude-code) simultaneously.' + 'Error: Cannot use multiple provider flags (--openrouter, --ollama, --bedrock, --claude-code, --gemini-cli) simultaneously.' ) ); process.exit(1); @@ -3497,7 +3510,9 @@ Examples: ? 'bedrock' : options.claudeCode ? 'claude-code' - : undefined + : options.geminiCli + ? 'gemini-cli' + : undefined }); if (result.success) { console.log(chalk.green(`✅ ${result.data.message}`)); @@ -3521,7 +3536,9 @@ Examples: ? 'bedrock' : options.claudeCode ? 'claude-code' - : undefined + : options.geminiCli + ? 'gemini-cli' + : undefined }); if (result.success) { console.log(chalk.green(`✅ ${result.data.message}`)); @@ -3547,7 +3564,9 @@ Examples: ? 'bedrock' : options.claudeCode ? 'claude-code' - : undefined + : options.geminiCli + ? 'gemini-cli' + : undefined }); if (result.success) { console.log(chalk.green(`✅ ${result.data.message}`)); @@ -3643,6 +3662,63 @@ Examples: return; // Stop execution here }); + // response-language command + programInstance + .command('lang') + .description('Manage response language settings') + .option('--response ', 'Set the response language') + .option('--setup', 'Run interactive setup to configure response language') + .action(async (options) => { + const projectRoot = findProjectRoot(); // Find project root for context + const { response, setup } = options; + console.log( + chalk.blue('Response language set to:', JSON.stringify(options)) + ); + let responseLanguage = response || 'English'; + if (setup) { + console.log( + chalk.blue('Starting interactive response language setup...') + ); + try { + const userResponse = await inquirer.prompt([ + { + type: 'input', + name: 'responseLanguage', + message: 'Input your preferred response language', + default: 'English' + } + ]); + + console.log( + chalk.blue( + 'Response language set to:', + userResponse.responseLanguage + ) + ); + responseLanguage = userResponse.responseLanguage; + } catch (setupError) { + console.error( + chalk.red('\\nInteractive setup failed unexpectedly:'), + setupError.message + ); + } + } + + const result = setResponseLanguage(responseLanguage, { + projectRoot + }); + + if (result.success) { + console.log(chalk.green(`✅ ${result.data.message}`)); + } else { + console.error( + chalk.red( + `❌ Error setting response language: ${result.error.message}` + ) + ); + } + }); + // move-task command programInstance .command('move') @@ -3810,7 +3886,11 @@ Examples: $ task-master rules --${RULES_SETUP_ACTION} # Interactive setup to select rule profiles` ) .action(async (action, profiles, options) => { - const projectDir = process.cwd(); + const projectRoot = findProjectRoot(); + if (!projectRoot) { + console.error(chalk.red('Error: Could not find project root.')); + process.exit(1); + } /** * 'task-master rules --setup' action: @@ -3857,7 +3937,7 @@ Examples: const profileConfig = getRulesProfile(profile); const addResult = convertAllRulesToProfileRules( - projectDir, + projectRoot, profileConfig ); @@ -3903,8 +3983,8 @@ Examples: let confirmed = true; if (!options.force) { // Check if this removal would leave no profiles remaining - if (wouldRemovalLeaveNoProfiles(projectDir, expandedProfiles)) { - const installedProfiles = getInstalledProfiles(projectDir); + if (wouldRemovalLeaveNoProfiles(projectRoot, expandedProfiles)) { + const installedProfiles = getInstalledProfiles(projectRoot); confirmed = await confirmRemoveAllRemainingProfiles( expandedProfiles, installedProfiles @@ -3934,12 +4014,12 @@ Examples: if (action === RULES_ACTIONS.ADD) { console.log(chalk.blue(`Adding rules for profile: ${profile}...`)); const addResult = convertAllRulesToProfileRules( - projectDir, + projectRoot, profileConfig ); if (typeof profileConfig.onAddRulesProfile === 'function') { - const assetsDir = path.join(process.cwd(), 'assets'); - profileConfig.onAddRulesProfile(projectDir, assetsDir); + const assetsDir = path.join(projectRoot, 'assets'); + profileConfig.onAddRulesProfile(projectRoot, assetsDir); } console.log( chalk.blue(`Completed adding rules for profile: ${profile}`) @@ -3955,7 +4035,7 @@ Examples: console.log(chalk.green(generateProfileSummary(profile, addResult))); } else if (action === RULES_ACTIONS.REMOVE) { console.log(chalk.blue(`Removing rules for profile: ${profile}...`)); - const result = removeProfileRules(projectDir, profileConfig); + const result = removeProfileRules(projectRoot, profileConfig); removalResults.push(result); console.log( chalk.green(generateProfileRemovalSummary(profile, result)) diff --git a/scripts/modules/config-manager.js b/scripts/modules/config-manager.js index 3ab36ff5..d226930a 100644 --- a/scripts/modules/config-manager.js +++ b/scripts/modules/config-manager.js @@ -1,8 +1,9 @@ import fs from 'fs'; import path from 'path'; import chalk from 'chalk'; +import { z } from 'zod'; import { fileURLToPath } from 'url'; -import { log, findProjectRoot, resolveEnvVariable } from './utils.js'; +import { log, findProjectRoot, resolveEnvVariable, isEmpty } from './utils.js'; import { LEGACY_CONFIG_FILE } from '../../src/constants/paths.js'; import { findConfigPath } from '../../src/utils/path-utils.js'; import { @@ -11,6 +12,7 @@ import { CUSTOM_PROVIDERS_ARRAY, ALL_PROVIDERS } from '../../src/constants/providers.js'; +import { AI_COMMAND_NAMES } from '../../src/constants/commands.js'; // Calculate __dirname in ESM const __filename = fileURLToPath(import.meta.url); @@ -61,12 +63,15 @@ const DEFAULTS = { global: { logLevel: 'info', debug: false, + defaultNumTasks: 10, defaultSubtasks: 5, defaultPriority: 'medium', projectName: 'Task Master', ollamaBaseURL: 'http://localhost:11434/api', - bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com' - } + bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com', + responseLanguage: 'English' + }, + claudeCode: {} }; // --- Internal Config Loading --- @@ -127,7 +132,8 @@ function _loadAndValidateConfig(explicitRoot = null) { ? { ...defaults.models.fallback, ...parsedConfig.models.fallback } : { ...defaults.models.fallback } }, - global: { ...defaults.global, ...parsedConfig?.global } + global: { ...defaults.global, ...parsedConfig?.global }, + claudeCode: { ...defaults.claudeCode, ...parsedConfig?.claudeCode } }; configSource = `file (${configPath})`; // Update source info @@ -170,6 +176,9 @@ function _loadAndValidateConfig(explicitRoot = null) { config.models.fallback.provider = undefined; config.models.fallback.modelId = undefined; } + if (config.claudeCode && !isEmpty(config.claudeCode)) { + config.claudeCode = validateClaudeCodeSettings(config.claudeCode); + } } catch (error) { // Use console.error for actual errors during parsing console.error( @@ -277,6 +286,83 @@ function validateProviderModelCombination(providerName, modelId) { ); } +/** + * Validates Claude Code AI provider custom settings + * @param {object} settings The settings to validate + * @returns {object} The validated settings + */ +function validateClaudeCodeSettings(settings) { + // Define the base settings schema without commandSpecific first + const BaseSettingsSchema = z.object({ + maxTurns: z.number().int().positive().optional(), + customSystemPrompt: z.string().optional(), + appendSystemPrompt: z.string().optional(), + permissionMode: z + .enum(['default', 'acceptEdits', 'plan', 'bypassPermissions']) + .optional(), + allowedTools: z.array(z.string()).optional(), + disallowedTools: z.array(z.string()).optional(), + mcpServers: z + .record( + z.string(), + z.object({ + type: z.enum(['stdio', 'sse']).optional(), + command: z.string(), + args: z.array(z.string()).optional(), + env: z.record(z.string()).optional(), + url: z.string().url().optional(), + headers: z.record(z.string()).optional() + }) + ) + .optional() + }); + + // Define CommandSpecificSchema using the base schema + const CommandSpecificSchema = z.record( + z.enum(AI_COMMAND_NAMES), + BaseSettingsSchema + ); + + // Define the full settings schema with commandSpecific + const SettingsSchema = BaseSettingsSchema.extend({ + commandSpecific: CommandSpecificSchema.optional() + }); + + let validatedSettings = {}; + + try { + validatedSettings = SettingsSchema.parse(settings); + } catch (error) { + console.warn( + chalk.yellow( + `Warning: Invalid Claude Code settings in config: ${error.message}. Falling back to default.` + ) + ); + + validatedSettings = {}; + } + + return validatedSettings; +} + +// --- Claude Code Settings Getters --- + +function getClaudeCodeSettings(explicitRoot = null, forceReload = false) { + const config = getConfig(explicitRoot, forceReload); + // Ensure Claude Code defaults are applied if Claude Code section is missing + return { ...DEFAULTS.claudeCode, ...(config?.claudeCode || {}) }; +} + +function getClaudeCodeSettingsForCommand( + commandName, + explicitRoot = null, + forceReload = false +) { + const settings = getClaudeCodeSettings(explicitRoot, forceReload); + const commandSpecific = settings?.commandSpecific || {}; + return { ...settings, ...commandSpecific[commandName] }; +} + // --- Role-Specific Getters --- function getModelConfigForRole(role, explicitRoot = null) { @@ -424,6 +510,11 @@ function getVertexLocation(explicitRoot = null) { return getGlobalConfig(explicitRoot).vertexLocation || 'us-central1'; } +function getResponseLanguage(explicitRoot = null) { + // Directly return value from config + return getGlobalConfig(explicitRoot).responseLanguage; +} + /** * Gets model parameters (maxTokens, temperature) for a specific role, * considering model-specific overrides from supported-models.json. @@ -500,7 +591,8 @@ function isApiKeySet(providerName, session = null, projectRoot = null) { // Providers that don't require API keys for authentication const providersWithoutApiKeys = [ CUSTOM_PROVIDERS.OLLAMA, - CUSTOM_PROVIDERS.BEDROCK + CUSTOM_PROVIDERS.BEDROCK, + CUSTOM_PROVIDERS.GEMINI_CLI ]; if (providersWithoutApiKeys.includes(providerName?.toLowerCase())) { @@ -794,15 +886,26 @@ function getBaseUrlForRole(role, explicitRoot = null) { return undefined; } +// Export the providers without API keys array for use in other modules +export const providersWithoutApiKeys = [ + CUSTOM_PROVIDERS.OLLAMA, + CUSTOM_PROVIDERS.BEDROCK, + CUSTOM_PROVIDERS.GEMINI_CLI +]; + export { // Core config access getConfig, writeConfig, ConfigurationError, isConfigFilePresent, + // Claude Code settings + getClaudeCodeSettings, + getClaudeCodeSettingsForCommand, // Validation validateProvider, validateProviderModelCombination, + validateClaudeCodeSettings, VALIDATED_PROVIDERS, CUSTOM_PROVIDERS, ALL_PROVIDERS, @@ -832,6 +935,7 @@ export { getOllamaBaseURL, getAzureBaseURL, getBedrockBaseURL, + getResponseLanguage, getParametersForRole, getUserId, // API Key Checkers (still relevant) diff --git a/scripts/modules/supported-models.json b/scripts/modules/supported-models.json index d57e77af..23f31ddb 100644 --- a/scripts/modules/supported-models.json +++ b/scripts/modules/supported-models.json @@ -1,16 +1,64 @@ { "bedrock": [ + { + "id": "us.anthropic.claude-3-haiku-20240307-v1:0", + "swe_score": 0.4, + "cost_per_1m_tokens": { "input": 0.25, "output": 1.25 }, + "allowed_roles": ["main", "fallback"] + }, + { + "id": "us.anthropic.claude-3-opus-20240229-v1:0", + "swe_score": 0.725, + "cost_per_1m_tokens": { "input": 15, "output": 75 }, + "allowed_roles": ["main", "fallback", "research"] + }, + { + "id": "us.anthropic.claude-3-5-sonnet-20240620-v1:0", + "swe_score": 0.49, + "cost_per_1m_tokens": { "input": 3, "output": 15 }, + "allowed_roles": ["main", "fallback", "research"] + }, + { + "id": "us.anthropic.claude-3-5-sonnet-20241022-v2:0", + "swe_score": 0.49, + "cost_per_1m_tokens": { "input": 3, "output": 15 }, + "allowed_roles": ["main", "fallback", "research"] + }, { "id": "us.anthropic.claude-3-7-sonnet-20250219-v1:0", "swe_score": 0.623, - "cost_per_1m_tokens": { "input": 3, "output": 15 }, - "allowed_roles": ["main", "fallback"], + "cost_per_1m_tokens": { + "input": 3, + "output": 15 + }, + "allowed_roles": ["main", "fallback", "research"], "max_tokens": 65536 }, + { + "id": "us.anthropic.claude-3-5-haiku-20241022-v1:0", + "swe_score": 0.4, + "cost_per_1m_tokens": { "input": 0.8, "output": 4 }, + "allowed_roles": ["main", "fallback"] + }, + { + "id": "us.anthropic.claude-opus-4-20250514-v1:0", + "swe_score": 0.725, + "cost_per_1m_tokens": { "input": 15, "output": 75 }, + "allowed_roles": ["main", "fallback", "research"] + }, + { + "id": "us.anthropic.claude-sonnet-4-20250514-v1:0", + "swe_score": 0.727, + "cost_per_1m_tokens": { "input": 3, "output": 15 }, + "allowed_roles": ["main", "fallback", "research"] + }, { "id": "us.deepseek.r1-v1:0", "swe_score": 0, - "cost_per_1m_tokens": { "input": 1.35, "output": 5.4 }, + "cost_per_1m_tokens": { + "input": 1.35, + "output": 5.4 + }, "allowed_roles": ["research"], "max_tokens": 65536 } @@ -648,16 +696,44 @@ { "id": "opus", "swe_score": 0.725, - "cost_per_1m_tokens": { "input": 0, "output": 0 }, + "cost_per_1m_tokens": { + "input": 0, + "output": 0 + }, "allowed_roles": ["main", "fallback", "research"], "max_tokens": 32000 }, { "id": "sonnet", "swe_score": 0.727, - "cost_per_1m_tokens": { "input": 0, "output": 0 }, + "cost_per_1m_tokens": { + "input": 0, + "output": 0 + }, "allowed_roles": ["main", "fallback", "research"], "max_tokens": 64000 } + ], + "gemini-cli": [ + { + "id": "gemini-2.5-pro", + "swe_score": 0.72, + "cost_per_1m_tokens": { + "input": 0, + "output": 0 + }, + "allowed_roles": ["main", "fallback", "research"], + "max_tokens": 65536 + }, + { + "id": "gemini-2.5-flash", + "swe_score": 0.71, + "cost_per_1m_tokens": { + "input": 0, + "output": 0 + }, + "allowed_roles": ["main", "fallback", "research"], + "max_tokens": 65536 + } ] } diff --git a/scripts/modules/task-manager.js b/scripts/modules/task-manager.js index e8af0023..7fab9d8f 100644 --- a/scripts/modules/task-manager.js +++ b/scripts/modules/task-manager.js @@ -23,10 +23,12 @@ import updateSubtaskById from './task-manager/update-subtask-by-id.js'; import removeTask from './task-manager/remove-task.js'; import taskExists from './task-manager/task-exists.js'; import isTaskDependentOn from './task-manager/is-task-dependent.js'; +import setResponseLanguage from './task-manager/response-language.js'; import moveTask from './task-manager/move-task.js'; import { migrateProject } from './task-manager/migrate.js'; import { performResearch } from './task-manager/research.js'; import { readComplexityReport } from './utils.js'; + // Export task manager functions export { parsePRD, @@ -49,6 +51,7 @@ export { findTaskById, taskExists, isTaskDependentOn, + setResponseLanguage, moveTask, readComplexityReport, migrateProject, diff --git a/scripts/modules/task-manager/add-subtask.js b/scripts/modules/task-manager/add-subtask.js index 83d0c9f2..b48a8dc9 100644 --- a/scripts/modules/task-manager/add-subtask.js +++ b/scripts/modules/task-manager/add-subtask.js @@ -1,6 +1,6 @@ import path from 'path'; -import { log, readJSON, writeJSON } from '../utils.js'; +import { log, readJSON, writeJSON, getCurrentTag } from '../utils.js'; import { isTaskDependentOn } from '../task-manager.js'; import generateTaskFiles from './generate-task-files.js'; @@ -25,8 +25,10 @@ async function addSubtask( try { log('info', `Adding subtask to parent task ${parentId}...`); + const currentTag = + context.tag || getCurrentTag(context.projectRoot) || 'master'; // Read the existing tasks with proper context - const data = readJSON(tasksPath, context.projectRoot, context.tag); + const data = readJSON(tasksPath, context.projectRoot, currentTag); if (!data || !data.tasks) { throw new Error(`Invalid or missing tasks file at ${tasksPath}`); } @@ -137,12 +139,12 @@ async function addSubtask( } // Write the updated tasks back to the file with proper context - writeJSON(tasksPath, data, context.projectRoot, context.tag); + writeJSON(tasksPath, data, context.projectRoot, currentTag); // Generate task files if requested if (generateFiles) { log('info', 'Regenerating task files...'); - // await generateTaskFiles(tasksPath, path.dirname(tasksPath), context); + await generateTaskFiles(tasksPath, path.dirname(tasksPath), context); } return newSubtask; diff --git a/scripts/modules/task-manager/add-task.js b/scripts/modules/task-manager/add-task.js index 1e94c05b..0fc29478 100644 --- a/scripts/modules/task-manager/add-task.js +++ b/scripts/modules/task-manager/add-task.js @@ -28,6 +28,7 @@ import { import { generateObjectService } from '../ai-services-unified.js'; import { getDefaultPriority } from '../config-manager.js'; import ContextGatherer from '../utils/contextGatherer.js'; +import generateTaskFiles from './generate-task-files.js'; // Define Zod schema for the expected AI output object const AiTaskDataSchema = z.object({ @@ -553,18 +554,18 @@ async function addTask( report('DEBUG: Writing tasks.json...', 'debug'); // Write the updated raw data back to the file // The writeJSON function will automatically filter out _rawTaggedData - writeJSON(tasksPath, rawData); + writeJSON(tasksPath, rawData, projectRoot, targetTag); report('DEBUG: tasks.json written.', 'debug'); // Generate markdown task files - // report('Generating task files...', 'info'); - // report('DEBUG: Calling generateTaskFiles...', 'debug'); - // // Pass mcpLog if available to generateTaskFiles - // await generateTaskFiles(tasksPath, path.dirname(tasksPath), { - // projectRoot, - // tag: targetTag - // }); - // report('DEBUG: generateTaskFiles finished.', 'debug'); + report('Generating task files...', 'info'); + report('DEBUG: Calling generateTaskFiles...', 'debug'); + // Pass mcpLog if available to generateTaskFiles + await generateTaskFiles(tasksPath, path.dirname(tasksPath), { + projectRoot, + tag: targetTag + }); + report('DEBUG: generateTaskFiles finished.', 'debug'); // Show success message - only for text output (CLI) if (outputFormat === 'text') { diff --git a/scripts/modules/task-manager/expand-task.js b/scripts/modules/task-manager/expand-task.js index eb928578..185411b8 100644 --- a/scripts/modules/task-manager/expand-task.js +++ b/scripts/modules/task-manager/expand-task.js @@ -2,7 +2,13 @@ import fs from 'fs'; import path from 'path'; import { z } from 'zod'; -import { log, readJSON, writeJSON, isSilentMode } from '../utils.js'; +import { + log, + readJSON, + writeJSON, + isSilentMode, + getTagAwareFilePath +} from '../utils.js'; import { startLoadingIndicator, @@ -61,7 +67,7 @@ const subtaskWrapperSchema = z.object({ */ function generateMainSystemPrompt(subtaskCount) { return `You are an AI assistant helping with task breakdown for software development. -You need to break down a high-level task into ${subtaskCount} specific subtasks that can be implemented one by one. +You need to break down a high-level task into ${subtaskCount > 0 ? subtaskCount : 'an appropriate number of'} specific subtasks that can be implemented one by one. Subtasks should: 1. Be specific and actionable implementation steps @@ -76,7 +82,7 @@ For each subtask, provide: - title: Clear, specific title - description: Detailed description - dependencies: Array of prerequisite subtask IDs (use the new sequential IDs) -- details: Implementation details +- details: Implementation details, the output should be in string - testStrategy: Optional testing approach @@ -111,11 +117,11 @@ function generateMainUserPrompt( "details": "Implementation guidance", "testStrategy": "Optional testing approach" }, - // ... (repeat for a total of ${subtaskCount} subtasks with sequential IDs) + // ... (repeat for ${subtaskCount ? 'a total of ' + subtaskCount : 'each of the'} subtasks with sequential IDs) ] }`; - return `Break down this task into exactly ${subtaskCount} specific subtasks: + return `Break down this task into ${subtaskCount > 0 ? 'exactly ' + subtaskCount : 'an appropriate number of'} specific subtasks: Task ID: ${task.id} Title: ${task.title} @@ -159,7 +165,7 @@ function generateResearchUserPrompt( ] }`; - return `Analyze the following task and break it down into exactly ${subtaskCount} specific subtasks using your research capabilities. Assign sequential IDs starting from ${nextSubtaskId}. + return `Analyze the following task and break it down into ${subtaskCount > 0 ? 'exactly ' + subtaskCount : 'an appropriate number of'} specific subtasks using your research capabilities. Assign sequential IDs starting from ${nextSubtaskId}. Parent Task: ID: ${task.id} @@ -497,9 +503,18 @@ async function expandTask( let complexityReasoningContext = ''; let systemPrompt; // Declare systemPrompt here - const complexityReportPath = path.join(projectRoot, COMPLEXITY_REPORT_FILE); + // Use tag-aware complexity report path + const complexityReportPath = getTagAwareFilePath( + COMPLEXITY_REPORT_FILE, + tag, + projectRoot + ); let taskAnalysis = null; + logger.info( + `Looking for complexity report at: ${complexityReportPath}${tag && tag !== 'master' ? ` (tag-specific for '${tag}')` : ''}` + ); + try { if (fs.existsSync(complexityReportPath)) { const complexityReport = readJSON(complexityReportPath); @@ -531,7 +546,7 @@ async function expandTask( // Determine final subtask count const explicitNumSubtasks = parseInt(numSubtasks, 10); - if (!Number.isNaN(explicitNumSubtasks) && explicitNumSubtasks > 0) { + if (!Number.isNaN(explicitNumSubtasks) && explicitNumSubtasks >= 0) { finalSubtaskCount = explicitNumSubtasks; logger.info( `Using explicitly provided subtask count: ${finalSubtaskCount}` @@ -545,7 +560,7 @@ async function expandTask( finalSubtaskCount = getDefaultSubtasks(session); logger.info(`Using default number of subtasks: ${finalSubtaskCount}`); } - if (Number.isNaN(finalSubtaskCount) || finalSubtaskCount <= 0) { + if (Number.isNaN(finalSubtaskCount) || finalSubtaskCount < 0) { logger.warn( `Invalid subtask count determined (${finalSubtaskCount}), defaulting to 3.` ); @@ -566,7 +581,7 @@ async function expandTask( } // --- Use Simplified System Prompt for Report Prompts --- - systemPrompt = `You are an AI assistant helping with task breakdown. Generate exactly ${finalSubtaskCount} subtasks based on the provided prompt and context. Respond ONLY with a valid JSON object containing a single key "subtasks" whose value is an array of the generated subtask objects. Each subtask object in the array must have keys: "id", "title", "description", "dependencies", "details", "status". Ensure the 'id' starts from ${nextSubtaskId} and is sequential. Ensure 'dependencies' only reference valid prior subtask IDs generated in this response (starting from ${nextSubtaskId}). Ensure 'status' is 'pending'. Do not include any other text or explanation.`; + systemPrompt = `You are an AI assistant helping with task breakdown. Generate ${finalSubtaskCount > 0 ? 'exactly ' + finalSubtaskCount : 'an appropriate number of'} subtasks based on the provided prompt and context. Respond ONLY with a valid JSON object containing a single key "subtasks" whose value is an array of the generated subtask objects. Each subtask object in the array must have keys: "id", "title", "description", "dependencies", "details", "status". Ensure the 'id' starts from ${nextSubtaskId} and is sequential. Ensure 'dependencies' only reference valid prior subtask IDs generated in this response (starting from ${nextSubtaskId}). Ensure 'status' is 'pending'. Do not include any other text or explanation.`; logger.info( `Using expansion prompt from complexity report and simplified system prompt for task ${task.id}.` ); @@ -608,7 +623,7 @@ async function expandTask( let loadingIndicator = null; if (outputFormat === 'text') { loadingIndicator = startLoadingIndicator( - `Generating ${finalSubtaskCount} subtasks...\n` + `Generating ${finalSubtaskCount || 'appropriate number of'} subtasks...\n` ); } diff --git a/scripts/modules/task-manager/generate-task-files.js b/scripts/modules/task-manager/generate-task-files.js index 17498db0..d5dba0d6 100644 --- a/scripts/modules/task-manager/generate-task-files.js +++ b/scripts/modules/task-manager/generate-task-files.js @@ -1,5 +1,5 @@ -import fs from 'fs'; import path from 'path'; +import fs from 'fs'; import chalk from 'chalk'; import { log, readJSON } from '../utils.js'; diff --git a/scripts/modules/task-manager/models.js b/scripts/modules/task-manager/models.js index 5a035858..229dda5b 100644 --- a/scripts/modules/task-manager/models.js +++ b/scripts/modules/task-manager/models.js @@ -523,6 +523,24 @@ async function setModel(role, modelId, options = {}) { determinedProvider = CUSTOM_PROVIDERS.VERTEX; warningMessage = `Warning: Custom Vertex AI model '${modelId}' set. Please ensure the model is valid and accessible in your Google Cloud project.`; report('warn', warningMessage); + } else if (providerHint === CUSTOM_PROVIDERS.GEMINI_CLI) { + // Gemini CLI provider - check if model exists in our list + determinedProvider = CUSTOM_PROVIDERS.GEMINI_CLI; + // Re-find modelData specifically for gemini-cli provider + const geminiCliModels = availableModels.filter( + (m) => m.provider === 'gemini-cli' + ); + const geminiCliModelData = geminiCliModels.find( + (m) => m.id === modelId + ); + if (geminiCliModelData) { + // Update modelData to the found gemini-cli model + modelData = geminiCliModelData; + report('info', `Setting Gemini CLI model '${modelId}'.`); + } else { + warningMessage = `Warning: Gemini CLI model '${modelId}' not found in supported models. Setting without validation.`; + report('warn', warningMessage); + } } else { // Invalid provider hint - should not happen with our constants throw new Error(`Invalid provider hint received: ${providerHint}`); diff --git a/scripts/modules/task-manager/parse-prd.js b/scripts/modules/task-manager/parse-prd.js index da8f59ab..5e5d16c4 100644 --- a/scripts/modules/task-manager/parse-prd.js +++ b/scripts/modules/task-manager/parse-prd.js @@ -188,7 +188,7 @@ Your task breakdown should incorporate this research, resulting in more detailed // Base system prompt for PRD parsing const systemPrompt = `You are an AI assistant specialized in analyzing Product Requirements Documents (PRDs) and generating a structured, logically ordered, dependency-aware and sequenced list of development tasks in JSON format.${researchPromptAddition} -Analyze the provided PRD content and generate approximately ${numTasks} top-level development tasks. If the complexity or the level of detail of the PRD is high, generate more tasks relative to the complexity of the PRD +Analyze the provided PRD content and generate ${numTasks > 0 ? 'approximately ' + numTasks : 'an appropriate number of'} top-level development tasks. If the complexity or the level of detail of the PRD is high, generate more tasks relative to the complexity of the PRD Each task should represent a logical unit of work needed to implement the requirements and focus on the most direct and effective way to implement the requirements without unnecessary complexity or overengineering. Include pseudo-code, implementation details, and test strategy for each task. Find the most up to date information to implement each task. Assign sequential IDs starting from ${nextId}. Infer title, description, details, and test strategy for each task based *only* on the PRD content. Set status to 'pending', dependencies to an empty array [], and priority to 'medium' initially for all tasks. @@ -207,7 +207,7 @@ Each task should follow this JSON structure: } Guidelines: -1. Unless complexity warrants otherwise, create exactly ${numTasks} tasks, numbered sequentially starting from ${nextId} +1. ${numTasks > 0 ? 'Unless complexity warrants otherwise' : 'Depending on the complexity'}, create ${numTasks > 0 ? 'exactly ' + numTasks : 'an appropriate number of'} tasks, numbered sequentially starting from ${nextId} 2. Each task should be atomic and focused on a single responsibility following the most up to date best practices and standards 3. Order tasks logically - consider dependencies and implementation sequence 4. Early tasks should focus on setup, core functionality first, then advanced features @@ -220,7 +220,7 @@ Guidelines: 11. Always aim to provide the most direct path to implementation, avoiding over-engineering or roundabout approaches${research ? '\n12. For each task, include specific, actionable guidance based on current industry standards and best practices discovered through research' : ''}`; // Build user prompt with PRD content - const userPrompt = `Here's the Product Requirements Document (PRD) to break down into approximately ${numTasks} tasks, starting IDs from ${nextId}:${research ? '\n\nRemember to thoroughly research current best practices and technologies before task breakdown to provide specific, actionable implementation details.' : ''}\n\n${prdContent}\n\n + const userPrompt = `Here's the Product Requirements Document (PRD) to break down into approximately ${numTasks > 0 ? 'approximately ' + numTasks : 'an appropriate number of'} tasks, starting IDs from ${nextId}:${research ? '\n\nRemember to thoroughly research current best practices and technologies before task breakdown to provide specific, actionable implementation details.' : ''}\n\n${prdContent}\n\n Return your response in this format: { @@ -235,7 +235,7 @@ Guidelines: ], "metadata": { "projectName": "PRD Implementation", - "totalTasks": ${numTasks}, + "totalTasks": {number of tasks}, "sourceFile": "${prdPath}", "generatedAt": "YYYY-MM-DD" } diff --git a/scripts/modules/task-manager/remove-task.js b/scripts/modules/task-manager/remove-task.js index de4382fa..0406482e 100644 --- a/scripts/modules/task-manager/remove-task.js +++ b/scripts/modules/task-manager/remove-task.js @@ -1,7 +1,6 @@ -import fs from 'fs'; import path from 'path'; - -import { log, readJSON, writeJSON } from '../utils.js'; +import * as fs from 'fs'; +import { readJSON, writeJSON, log, findTaskById } from '../utils.js'; import generateTaskFiles from './generate-task-files.js'; import taskExists from './task-exists.js'; @@ -172,7 +171,7 @@ async function removeTask(tasksPath, taskIds, context = {}) { } // Save the updated raw data structure - writeJSON(tasksPath, fullTaggedData); + writeJSON(tasksPath, fullTaggedData, projectRoot, currentTag); // Delete task files AFTER saving tasks.json for (const taskIdNum of tasksToDeleteFiles) { @@ -195,10 +194,10 @@ async function removeTask(tasksPath, taskIds, context = {}) { // Generate updated task files ONCE, with context try { - // await generateTaskFiles(tasksPath, path.dirname(tasksPath), { - // projectRoot, - // tag: currentTag - // }); + await generateTaskFiles(tasksPath, path.dirname(tasksPath), { + projectRoot, + tag: currentTag + }); results.messages.push('Task files regenerated successfully.'); } catch (genError) { const genErrMsg = `Failed to regenerate task files: ${genError.message}`; diff --git a/scripts/modules/task-manager/response-language.js b/scripts/modules/task-manager/response-language.js new file mode 100644 index 00000000..90be4c1a --- /dev/null +++ b/scripts/modules/task-manager/response-language.js @@ -0,0 +1,89 @@ +import { + getConfig, + isConfigFilePresent, + writeConfig +} from '../config-manager.js'; +import { findConfigPath } from '../../../src/utils/path-utils.js'; +import { log } from '../utils.js'; + +function setResponseLanguage(lang, options = {}) { + const { mcpLog, projectRoot } = options; + + const report = (level, ...args) => { + if (mcpLog && typeof mcpLog[level] === 'function') { + mcpLog[level](...args); + } + }; + + // Use centralized config path finding instead of hardcoded path + const configPath = findConfigPath(null, { projectRoot }); + const configExists = isConfigFilePresent(projectRoot); + + log( + 'debug', + `Checking for config file using findConfigPath, found: ${configPath}` + ); + log( + 'debug', + `Checking config file using isConfigFilePresent(), exists: ${configExists}` + ); + + if (!configExists) { + return { + success: false, + error: { + code: 'CONFIG_MISSING', + message: + 'The configuration file is missing. Run "task-master models --setup" to create it.' + } + }; + } + + // Validate response language + if (typeof lang !== 'string' || lang.trim() === '') { + return { + success: false, + error: { + code: 'INVALID_RESPONSE_LANGUAGE', + message: `Invalid response language: ${lang}. Must be a non-empty string.` + } + }; + } + + try { + const currentConfig = getConfig(projectRoot); + currentConfig.global.responseLanguage = lang; + const writeResult = writeConfig(currentConfig, projectRoot); + + if (!writeResult) { + return { + success: false, + error: { + code: 'WRITE_ERROR', + message: 'Error writing updated configuration to configuration file' + } + }; + } + + const successMessage = `Successfully set response language to: ${lang}`; + report('info', successMessage); + return { + success: true, + data: { + responseLanguage: lang, + message: successMessage + } + }; + } catch (error) { + report('error', `Error setting response language: ${error.message}`); + return { + success: false, + error: { + code: 'SET_RESPONSE_LANGUAGE_ERROR', + message: error.message + } + }; + } +} + +export default setResponseLanguage; diff --git a/scripts/modules/task-manager/set-task-status.js b/scripts/modules/task-manager/set-task-status.js index 9a08fcba..218aad3d 100644 --- a/scripts/modules/task-manager/set-task-status.js +++ b/scripts/modules/task-manager/set-task-status.js @@ -132,7 +132,7 @@ async function setTaskStatus( // Write the updated raw data back to the file // The writeJSON function will automatically filter out _rawTaggedData - writeJSON(tasksPath, rawData); + writeJSON(tasksPath, rawData, options.projectRoot, currentTag); // Validate dependencies after status update log('info', 'Validating dependencies after status update...'); diff --git a/scripts/modules/task-manager/tag-management.js b/scripts/modules/task-manager/tag-management.js index 65a80e35..c17f7068 100644 --- a/scripts/modules/task-manager/tag-management.js +++ b/scripts/modules/task-manager/tag-management.js @@ -145,8 +145,8 @@ async function createTag( } } - // Write the clean data back to file - writeJSON(tasksPath, cleanData); + // Write the clean data back to file with proper context to avoid tag corruption + writeJSON(tasksPath, cleanData, projectRoot); logFn.success(`Successfully created tag "${tagName}"`); @@ -365,8 +365,8 @@ async function deleteTag( } } - // Write the clean data back to file - writeJSON(tasksPath, cleanData); + // Write the clean data back to file with proper context to avoid tag corruption + writeJSON(tasksPath, cleanData, projectRoot); logFn.success(`Successfully deleted tag "${tagName}"`); @@ -485,7 +485,7 @@ async function enhanceTagsWithMetadata(tasksPath, rawData, context = {}) { cleanData[key] = value; } } - writeJSON(tasksPath, cleanData); + writeJSON(tasksPath, cleanData, context.projectRoot); } } catch (error) { // Don't throw - just log and continue @@ -905,8 +905,8 @@ async function renameTag( } } - // Write the clean data back to file - writeJSON(tasksPath, cleanData); + // Write the clean data back to file with proper context to avoid tag corruption + writeJSON(tasksPath, cleanData, projectRoot); // Get task count const tasks = getTasksForTag(rawData, newName); @@ -1062,8 +1062,8 @@ async function copyTag( } } - // Write the clean data back to file - writeJSON(tasksPath, cleanData); + // Write the clean data back to file with proper context to avoid tag corruption + writeJSON(tasksPath, cleanData, projectRoot); logFn.success( `Successfully copied tag from "${sourceName}" to "${targetName}"` diff --git a/scripts/modules/task-manager/update-tasks.js b/scripts/modules/task-manager/update-tasks.js index 48b1d541..528f81e2 100644 --- a/scripts/modules/task-manager/update-tasks.js +++ b/scripts/modules/task-manager/update-tasks.js @@ -9,7 +9,8 @@ import { readJSON, writeJSON, truncate, - isSilentMode + isSilentMode, + getCurrentTag } from '../utils.js'; import { @@ -222,6 +223,7 @@ function parseUpdatedTasksFromText(text, expectedCount, logFn, isMCP) { * @param {Object} [context.session] - Session object from MCP server. * @param {Object} [context.mcpLog] - MCP logger object. * @param {string} [outputFormat='text'] - Output format ('text' or 'json'). + * @param {string} [tag=null] - Tag associated with the tasks. */ async function updateTasks( tasksPath, @@ -231,7 +233,7 @@ async function updateTasks( context = {}, outputFormat = 'text' // Default to text for CLI ) { - const { session, mcpLog, projectRoot: providedProjectRoot } = context; + const { session, mcpLog, projectRoot: providedProjectRoot, tag } = context; // Use mcpLog if available, otherwise use the imported consoleLog function const logFn = mcpLog || consoleLog; // Flag to easily check which logger type we have @@ -255,8 +257,11 @@ async function updateTasks( throw new Error('Could not determine project root directory'); } - // --- Task Loading/Filtering (Unchanged) --- - const data = readJSON(tasksPath, projectRoot); + // Determine the current tag - prioritize explicit tag, then context.tag, then current tag + const currentTag = tag || getCurrentTag(projectRoot) || 'master'; + + // --- Task Loading/Filtering (Updated to pass projectRoot and tag) --- + const data = readJSON(tasksPath, projectRoot, currentTag); if (!data || !data.tasks) throw new Error(`No valid tasks found in ${tasksPath}`); const tasksToUpdate = data.tasks.filter( @@ -428,7 +433,7 @@ The changes described in the prompt should be applied to ALL tasks in the list.` isMCP ); - // --- Update Tasks Data (Unchanged) --- + // --- Update Tasks Data (Updated writeJSON call) --- if (!Array.isArray(parsedUpdatedTasks)) { // Should be caught by parser, but extra check throw new Error( @@ -467,7 +472,8 @@ The changes described in the prompt should be applied to ALL tasks in the list.` `Applied updates to ${actualUpdateCount} tasks in the dataset.` ); - writeJSON(tasksPath, data); + // Fix: Pass projectRoot and currentTag to writeJSON + writeJSON(tasksPath, data, projectRoot, currentTag); if (isMCP) logFn.info( `Successfully updated ${actualUpdateCount} tasks in ${tasksPath}` diff --git a/scripts/modules/update-config-tokens.js b/scripts/modules/update-config-tokens.js new file mode 100644 index 00000000..14e68b2d --- /dev/null +++ b/scripts/modules/update-config-tokens.js @@ -0,0 +1,57 @@ +/** + * update-config-tokens.js + * Updates config.json with correct maxTokens values from supported-models.json + */ + +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +/** + * Updates the config file with correct maxTokens values from supported-models.json + * @param {string} configPath - Path to the config.json file to update + * @returns {boolean} True if successful, false otherwise + */ +export function updateConfigMaxTokens(configPath) { + try { + // Load supported models + const supportedModelsPath = path.join(__dirname, 'supported-models.json'); + const supportedModels = JSON.parse( + fs.readFileSync(supportedModelsPath, 'utf-8') + ); + + // Load config + const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); + + // Update each role's maxTokens if the model exists in supported-models.json + const roles = ['main', 'research', 'fallback']; + + for (const role of roles) { + if (config.models && config.models[role]) { + const provider = config.models[role].provider; + const modelId = config.models[role].modelId; + + // Find the model in supported models + if (supportedModels[provider]) { + const modelData = supportedModels[provider].find( + (m) => m.id === modelId + ); + if (modelData && modelData.max_tokens) { + config.models[role].maxTokens = modelData.max_tokens; + } + } + } + } + + // Write back the updated config + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); + return true; + } catch (error) { + console.error('Error updating config maxTokens:', error.message); + return false; + } +} diff --git a/scripts/modules/utils.js b/scripts/modules/utils.js index 5ec6fc55..1f99ea07 100644 --- a/scripts/modules/utils.js +++ b/scripts/modules/utils.js @@ -64,6 +64,51 @@ function resolveEnvVariable(key, session = null, projectRoot = null) { return undefined; } +// --- Tag-Aware Path Resolution Utility --- + +/** + * Slugifies a tag name to be filesystem-safe + * @param {string} tagName - The tag name to slugify + * @returns {string} Slugified tag name safe for filesystem use + */ +function slugifyTagForFilePath(tagName) { + if (!tagName || typeof tagName !== 'string') { + return 'unknown-tag'; + } + + // Replace invalid filesystem characters with hyphens and clean up + return tagName + .replace(/[^a-zA-Z0-9_-]/g, '-') // Replace invalid chars with hyphens + .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens + .replace(/-+/g, '-') // Collapse multiple hyphens + .toLowerCase() // Convert to lowercase + .substring(0, 50); // Limit length to prevent overly long filenames +} + +/** + * Resolves a file path to be tag-aware, following the pattern used by other commands. + * For non-master tags, appends _slugified-tagname before the file extension. + * @param {string} basePath - The base file path (e.g., '.taskmaster/reports/task-complexity-report.json') + * @param {string|null} tag - The tag name (null, undefined, or 'master' uses base path) + * @param {string} [projectRoot='.'] - The project root directory + * @returns {string} The resolved file path + */ +function getTagAwareFilePath(basePath, tag, projectRoot = '.') { + // Use path.parse and format for clean tag insertion + const parsedPath = path.parse(basePath); + if (!tag || tag === 'master') { + return path.join(projectRoot, basePath); + } + + // Slugify the tag for filesystem safety + const slugifiedTag = slugifyTagForFilePath(tag); + + // Append slugified tag before file extension + parsedPath.base = `${parsedPath.name}_${slugifiedTag}${parsedPath.ext}`; + const relativePath = path.format(parsedPath); + return path.join(projectRoot, relativePath); +} + // --- Project Root Finding Utility --- /** * Recursively searches upwards for project root starting from a given directory. @@ -967,6 +1012,21 @@ function truncate(text, maxLength) { return `${text.slice(0, maxLength - 3)}...`; } +/** + * Checks if array or object are empty + * @param {*} value - The value to check + * @returns {boolean} True if empty, false otherwise + */ +function isEmpty(value) { + if (Array.isArray(value)) { + return value.length === 0; + } else if (typeof value === 'object' && value !== null) { + return Object.keys(value).length === 0; + } + + return false; // Not an array or object, or is null +} + /** * Find cycles in a dependency graph using DFS * @param {string} subtaskId - Current subtask ID @@ -1328,6 +1388,7 @@ export { formatTaskId, findTaskById, truncate, + isEmpty, findCycles, toKebabCase, detectCamelCaseFlags, @@ -1338,6 +1399,8 @@ export { addComplexityToTask, resolveEnvVariable, findProjectRoot, + getTagAwareFilePath, + slugifyTagForFilePath, aggregateTelemetry, getCurrentTag, resolveTag, diff --git a/src/ai-providers/base-provider.js b/src/ai-providers/base-provider.js index c0ad3c05..1c203117 100644 --- a/src/ai-providers/base-provider.js +++ b/src/ai-providers/base-provider.js @@ -1,4 +1,4 @@ -import { generateText, streamText, generateObject } from 'ai'; +import { generateObject, generateText, streamText } from 'ai'; import { log } from '../../scripts/modules/index.js'; /** @@ -109,7 +109,7 @@ export class BaseAIProvider { `Generating ${this.name} text with model: ${params.modelId}` ); - const client = this.getClient(params); + const client = await this.getClient(params); const result = await generateText({ model: client(params.modelId), messages: params.messages, @@ -145,7 +145,7 @@ export class BaseAIProvider { log('debug', `Streaming ${this.name} text with model: ${params.modelId}`); - const client = this.getClient(params); + const client = await this.getClient(params); const stream = await streamText({ model: client(params.modelId), messages: params.messages, @@ -184,7 +184,7 @@ export class BaseAIProvider { `Generating ${this.name} object ('${params.objectName}') with model: ${params.modelId}` ); - const client = this.getClient(params); + const client = await this.getClient(params); const result = await generateObject({ model: client(params.modelId), messages: params.messages, diff --git a/src/ai-providers/claude-code.js b/src/ai-providers/claude-code.js index c84ff439..59f09759 100644 --- a/src/ai-providers/claude-code.js +++ b/src/ai-providers/claude-code.js @@ -7,6 +7,7 @@ import { createClaudeCode } from './custom-sdk/claude-code/index.js'; import { BaseAIProvider } from './base-provider.js'; +import { getClaudeCodeSettingsForCommand } from '../../scripts/modules/config-manager.js'; export class ClaudeCodeProvider extends BaseAIProvider { constructor() { @@ -26,6 +27,7 @@ export class ClaudeCodeProvider extends BaseAIProvider { /** * Creates and returns a Claude Code client instance. * @param {object} params - Parameters for client initialization + * @param {string} [params.commandName] - Name of the command invoking the service * @param {string} [params.baseURL] - Optional custom API endpoint (not used by Claude Code) * @returns {Function} Claude Code client function * @throws {Error} If initialization fails @@ -35,10 +37,7 @@ export class ClaudeCodeProvider extends BaseAIProvider { // Claude Code doesn't use API keys or base URLs // Just return the provider factory return createClaudeCode({ - defaultSettings: { - // Add any default settings if needed - // These can be overridden per request - } + defaultSettings: getClaudeCodeSettingsForCommand(params?.commandName) }); } catch (error) { this.handleError('client initialization', error); diff --git a/src/ai-providers/gemini-cli.js b/src/ai-providers/gemini-cli.js new file mode 100644 index 00000000..a96cb048 --- /dev/null +++ b/src/ai-providers/gemini-cli.js @@ -0,0 +1,656 @@ +/** + * src/ai-providers/gemini-cli.js + * + * Implementation for interacting with Gemini models via Gemini CLI + * using the ai-sdk-provider-gemini-cli package. + */ + +import { generateObject, generateText, streamText } from 'ai'; +import { parse } from 'jsonc-parser'; +import { BaseAIProvider } from './base-provider.js'; +import { log } from '../../scripts/modules/index.js'; + +let createGeminiProvider; + +async function loadGeminiCliModule() { + if (!createGeminiProvider) { + try { + const mod = await import('ai-sdk-provider-gemini-cli'); + createGeminiProvider = mod.createGeminiProvider; + } catch (err) { + throw new Error( + "Gemini CLI SDK is not installed. Please install 'ai-sdk-provider-gemini-cli' to use the gemini-cli provider." + ); + } + } +} + +export class GeminiCliProvider extends BaseAIProvider { + constructor() { + super(); + this.name = 'Gemini CLI'; + } + + /** + * Override validateAuth to handle Gemini CLI authentication options + * @param {object} params - Parameters to validate + */ + validateAuth(params) { + // Gemini CLI is designed to use pre-configured OAuth authentication + // Users choose gemini-cli specifically to leverage their existing + // gemini auth login credentials, not to use API keys. + // We support API keys for compatibility, but the expected usage + // is through CLI authentication (no API key required). + // No validation needed - the SDK will handle auth internally + } + + /** + * Creates and returns a Gemini CLI client instance. + * @param {object} params - Parameters for client initialization + * @param {string} [params.apiKey] - Optional Gemini API key (rarely used with gemini-cli) + * @param {string} [params.baseURL] - Optional custom API endpoint + * @returns {Promise} Gemini CLI client function + * @throws {Error} If initialization fails + */ + async getClient(params) { + try { + // Load the Gemini CLI module dynamically + await loadGeminiCliModule(); + // Primary use case: Use existing gemini CLI authentication + // Secondary use case: Direct API key (for compatibility) + let authOptions = {}; + + if (params.apiKey && params.apiKey !== 'gemini-cli-no-key-required') { + // API key provided - use it for compatibility + authOptions = { + authType: 'api-key', + apiKey: params.apiKey + }; + } else { + // Expected case: Use gemini CLI authentication + // Requires: gemini auth login (pre-configured) + authOptions = { + authType: 'oauth-personal' + }; + } + + // Add baseURL if provided (for custom endpoints) + if (params.baseURL) { + authOptions.baseURL = params.baseURL; + } + + // Create and return the provider + return createGeminiProvider(authOptions); + } catch (error) { + this.handleError('client initialization', error); + } + } + + /** + * Extracts system messages from the messages array and returns them separately. + * This is needed because ai-sdk-provider-gemini-cli expects system prompts as a separate parameter. + * @param {Array} messages - Array of message objects + * @param {Object} options - Options for system prompt enhancement + * @param {boolean} options.enforceJsonOutput - Whether to add JSON enforcement to system prompt + * @returns {Object} - {systemPrompt: string|undefined, messages: Array} + */ + _extractSystemMessage(messages, options = {}) { + if (!messages || !Array.isArray(messages)) { + return { systemPrompt: undefined, messages: messages || [] }; + } + + const systemMessages = messages.filter((msg) => msg.role === 'system'); + const nonSystemMessages = messages.filter((msg) => msg.role !== 'system'); + + // Combine multiple system messages if present + let systemPrompt = + systemMessages.length > 0 + ? systemMessages.map((msg) => msg.content).join('\n\n') + : undefined; + + // Add Gemini CLI specific JSON enforcement if requested + if (options.enforceJsonOutput) { + const jsonEnforcement = this._getJsonEnforcementPrompt(); + systemPrompt = systemPrompt + ? `${systemPrompt}\n\n${jsonEnforcement}` + : jsonEnforcement; + } + + return { systemPrompt, messages: nonSystemMessages }; + } + + /** + * Gets a Gemini CLI specific system prompt to enforce strict JSON output + * @returns {string} JSON enforcement system prompt + */ + _getJsonEnforcementPrompt() { + return `CRITICAL: You MUST respond with ONLY valid JSON. Do not include any explanatory text, markdown formatting, code block markers, or conversational phrases like "Here is" or "Of course". Your entire response must be parseable JSON that starts with { or [ and ends with } or ]. No exceptions.`; + } + + /** + * Checks if a string is valid JSON + * @param {string} text - Text to validate + * @returns {boolean} True if valid JSON + */ + _isValidJson(text) { + if (!text || typeof text !== 'string') { + return false; + } + + try { + JSON.parse(text.trim()); + return true; + } catch { + return false; + } + } + + /** + * Detects if the user prompt is requesting JSON output + * @param {Array} messages - Array of message objects + * @returns {boolean} True if JSON output is likely expected + */ + _detectJsonRequest(messages) { + const userMessages = messages.filter((msg) => msg.role === 'user'); + const combinedText = userMessages + .map((msg) => msg.content) + .join(' ') + .toLowerCase(); + + // Look for indicators that JSON output is expected + const jsonIndicators = [ + 'json', + 'respond only with', + 'return only', + 'output only', + 'format:', + 'structure:', + 'schema:', + '{"', + '[{', + 'subtasks', + 'array', + 'object' + ]; + + return jsonIndicators.some((indicator) => combinedText.includes(indicator)); + } + + /** + * Simplifies complex prompts for gemini-cli to improve JSON output compliance + * @param {Array} messages - Array of message objects + * @returns {Array} Simplified messages array + */ + _simplifyJsonPrompts(messages) { + // First, check if this is an expand-task operation by looking at the system message + const systemMsg = messages.find((m) => m.role === 'system'); + const isExpandTask = + systemMsg && + systemMsg.content.includes( + 'You are an AI assistant helping with task breakdown. Generate exactly' + ); + + if (!isExpandTask) { + return messages; // Not an expand task, return unchanged + } + + // Extract subtask count from system message + const subtaskCountMatch = systemMsg.content.match( + /Generate exactly (\d+) subtasks/ + ); + const subtaskCount = subtaskCountMatch ? subtaskCountMatch[1] : '10'; + + log( + 'debug', + `${this.name} detected expand-task operation, simplifying for ${subtaskCount} subtasks` + ); + + return messages.map((msg) => { + if (msg.role !== 'user') { + return msg; + } + + // For expand-task user messages, create a much simpler, more direct prompt + // that doesn't depend on specific task content + const simplifiedPrompt = `Generate exactly ${subtaskCount} subtasks in the following JSON format. + +CRITICAL INSTRUCTION: You must respond with ONLY valid JSON. No explanatory text, no "Here is", no "Of course", no markdown - just the JSON object. + +Required JSON structure: +{ + "subtasks": [ + { + "id": 1, + "title": "Specific actionable task title", + "description": "Clear task description", + "dependencies": [], + "details": "Implementation details and guidance", + "testStrategy": "Testing approach" + } + ] +} + +Generate ${subtaskCount} subtasks based on the original task context. Return ONLY the JSON object.`; + + log( + 'debug', + `${this.name} simplified user prompt for better JSON compliance` + ); + return { ...msg, content: simplifiedPrompt }; + }); + } + + /** + * Extract JSON from Gemini's response using a tolerant parser. + * + * Optimized approach that progressively tries different parsing strategies: + * 1. Direct parsing after cleanup + * 2. Smart boundary detection with single-pass analysis + * 3. Limited character-by-character fallback for edge cases + * + * @param {string} text - Raw text which may contain JSON + * @returns {string} A valid JSON string if extraction succeeds, otherwise the original text + */ + extractJson(text) { + if (!text || typeof text !== 'string') { + return text; + } + + let content = text.trim(); + + // Early exit for very short content + if (content.length < 2) { + return text; + } + + // Strip common wrappers in a single pass + content = content + // Remove markdown fences + .replace(/^.*?```(?:json)?\s*([\s\S]*?)\s*```.*$/i, '$1') + // Remove variable declarations + .replace(/^\s*(?:const|let|var)\s+\w+\s*=\s*([\s\S]*?)(?:;|\s*)$/i, '$1') + // Remove common prefixes + .replace(/^(?:Here's|The)\s+(?:the\s+)?JSON.*?[:]\s*/i, '') + .trim(); + + // Find the first JSON-like structure + const firstObj = content.indexOf('{'); + const firstArr = content.indexOf('['); + + if (firstObj === -1 && firstArr === -1) { + return text; + } + + const start = + firstArr === -1 + ? firstObj + : firstObj === -1 + ? firstArr + : Math.min(firstObj, firstArr); + content = content.slice(start); + + // Optimized parsing function with error collection + const tryParse = (value) => { + if (!value || value.length < 2) return undefined; + + const errors = []; + try { + const result = parse(value, errors, { + allowTrailingComma: true, + allowEmptyContent: false + }); + if (errors.length === 0 && result !== undefined) { + return JSON.stringify(result, null, 2); + } + } catch { + // Parsing failed completely + } + return undefined; + }; + + // Try parsing the full content first + const fullParse = tryParse(content); + if (fullParse !== undefined) { + return fullParse; + } + + // Smart boundary detection - single pass with optimizations + const openChar = content[0]; + const closeChar = openChar === '{' ? '}' : ']'; + + let depth = 0; + let inString = false; + let escapeNext = false; + let lastValidEnd = -1; + + // Single-pass boundary detection with early termination + for (let i = 0; i < content.length && i < 10000; i++) { + // Limit scan for performance + const char = content[i]; + + if (escapeNext) { + escapeNext = false; + continue; + } + + if (char === '\\') { + escapeNext = true; + continue; + } + + if (char === '"') { + inString = !inString; + continue; + } + + if (inString) continue; + + if (char === openChar) { + depth++; + } else if (char === closeChar) { + depth--; + if (depth === 0) { + lastValidEnd = i + 1; + // Try parsing immediately on first valid boundary + const candidate = content.slice(0, lastValidEnd); + const parsed = tryParse(candidate); + if (parsed !== undefined) { + return parsed; + } + } + } + } + + // If we found valid boundaries but parsing failed, try limited fallback + if (lastValidEnd > 0) { + const maxAttempts = Math.min(5, Math.floor(lastValidEnd / 100)); // Limit attempts + for (let i = 0; i < maxAttempts; i++) { + const testEnd = Math.max( + lastValidEnd - i * 50, + Math.floor(lastValidEnd * 0.8) + ); + const candidate = content.slice(0, testEnd); + const parsed = tryParse(candidate); + if (parsed !== undefined) { + return parsed; + } + } + } + + return text; + } + + /** + * Generates text using Gemini CLI model + * Overrides base implementation to properly handle system messages and enforce JSON output when needed + */ + async generateText(params) { + try { + this.validateParams(params); + this.validateMessages(params.messages); + + log( + 'debug', + `Generating ${this.name} text with model: ${params.modelId}` + ); + + // Detect if JSON output is expected and enforce it for better gemini-cli compatibility + const enforceJsonOutput = this._detectJsonRequest(params.messages); + + // Debug logging to understand what's happening + log('debug', `${this.name} JSON detection analysis:`, { + enforceJsonOutput, + messageCount: params.messages.length, + messages: params.messages.map((msg) => ({ + role: msg.role, + contentPreview: msg.content + ? msg.content.substring(0, 200) + '...' + : 'empty' + })) + }); + + if (enforceJsonOutput) { + log( + 'debug', + `${this.name} detected JSON request - applying strict JSON enforcement system prompt` + ); + } + + // For gemini-cli, simplify complex prompts before processing + let processedMessages = params.messages; + if (enforceJsonOutput) { + processedMessages = this._simplifyJsonPrompts(params.messages); + } + + // Extract system messages for separate handling with optional JSON enforcement + const { systemPrompt, messages } = this._extractSystemMessage( + processedMessages, + { enforceJsonOutput } + ); + + // Debug the final system prompt being sent + log('debug', `${this.name} final system prompt:`, { + systemPromptLength: systemPrompt ? systemPrompt.length : 0, + systemPromptPreview: systemPrompt + ? systemPrompt.substring(0, 300) + '...' + : 'none', + finalMessageCount: messages.length + }); + + const client = await this.getClient(params); + const result = await generateText({ + model: client(params.modelId), + system: systemPrompt, + messages: messages, + maxTokens: params.maxTokens, + temperature: params.temperature + }); + + // If we detected a JSON request and gemini-cli returned conversational text, + // attempt to extract JSON from the response + let finalText = result.text; + if (enforceJsonOutput && result.text && !this._isValidJson(result.text)) { + log( + 'debug', + `${this.name} response appears conversational, attempting JSON extraction` + ); + + // Log first 1000 chars of the response to see what Gemini actually returned + log('debug', `${this.name} raw response preview:`, { + responseLength: result.text.length, + responseStart: result.text.substring(0, 1000) + }); + + const extractedJson = this.extractJson(result.text); + if (this._isValidJson(extractedJson)) { + log( + 'debug', + `${this.name} successfully extracted JSON from conversational response` + ); + finalText = extractedJson; + } else { + log( + 'debug', + `${this.name} JSON extraction failed, returning original response` + ); + + // Log what extraction returned to debug why it failed + log('debug', `${this.name} extraction result preview:`, { + extractedLength: extractedJson ? extractedJson.length : 0, + extractedStart: extractedJson + ? extractedJson.substring(0, 500) + : 'null' + }); + } + } + + log( + 'debug', + `${this.name} generateText completed successfully for model: ${params.modelId}` + ); + + return { + text: finalText, + usage: { + inputTokens: result.usage?.promptTokens, + outputTokens: result.usage?.completionTokens, + totalTokens: result.usage?.totalTokens + } + }; + } catch (error) { + this.handleError('text generation', error); + } + } + + /** + * Streams text using Gemini CLI model + * Overrides base implementation to properly handle system messages and enforce JSON output when needed + */ + async streamText(params) { + try { + this.validateParams(params); + this.validateMessages(params.messages); + + log('debug', `Streaming ${this.name} text with model: ${params.modelId}`); + + // Detect if JSON output is expected and enforce it for better gemini-cli compatibility + const enforceJsonOutput = this._detectJsonRequest(params.messages); + + // Debug logging to understand what's happening + log('debug', `${this.name} JSON detection analysis:`, { + enforceJsonOutput, + messageCount: params.messages.length, + messages: params.messages.map((msg) => ({ + role: msg.role, + contentPreview: msg.content + ? msg.content.substring(0, 200) + '...' + : 'empty' + })) + }); + + if (enforceJsonOutput) { + log( + 'debug', + `${this.name} detected JSON request - applying strict JSON enforcement system prompt` + ); + } + + // Extract system messages for separate handling with optional JSON enforcement + const { systemPrompt, messages } = this._extractSystemMessage( + params.messages, + { enforceJsonOutput } + ); + + const client = await this.getClient(params); + const stream = await streamText({ + model: client(params.modelId), + system: systemPrompt, + messages: messages, + maxTokens: params.maxTokens, + temperature: params.temperature + }); + + log( + 'debug', + `${this.name} streamText initiated successfully for model: ${params.modelId}` + ); + + // Note: For streaming, we can't intercept and modify the response in real-time + // The JSON extraction would need to happen on the consuming side + return stream; + } catch (error) { + this.handleError('text streaming', error); + } + } + + /** + * Generates a structured object using Gemini CLI model + * Overrides base implementation to handle Gemini-specific JSON formatting issues and system messages + */ + async generateObject(params) { + try { + // First try the standard generateObject from base class + return await super.generateObject(params); + } catch (error) { + // If it's a JSON parsing error, try to extract and parse JSON manually + if (error.message?.includes('JSON') || error.message?.includes('parse')) { + log( + 'debug', + `Gemini CLI generateObject failed with parsing error, attempting manual extraction` + ); + + try { + // Validate params first + this.validateParams(params); + this.validateMessages(params.messages); + + if (!params.schema) { + throw new Error('Schema is required for object generation'); + } + if (!params.objectName) { + throw new Error('Object name is required for object generation'); + } + + // Extract system messages for separate handling with JSON enforcement + const { systemPrompt, messages } = this._extractSystemMessage( + params.messages, + { enforceJsonOutput: true } + ); + + // Call generateObject directly with our client + const client = await this.getClient(params); + const result = await generateObject({ + model: client(params.modelId), + system: systemPrompt, + messages: messages, + schema: params.schema, + mode: 'json', // Use json mode instead of auto for Gemini + maxTokens: params.maxTokens, + temperature: params.temperature + }); + + // If we get rawResponse text, try to extract JSON from it + if (result.rawResponse?.text && !result.object) { + const extractedJson = this.extractJson(result.rawResponse.text); + try { + result.object = JSON.parse(extractedJson); + } catch (parseError) { + log( + 'error', + `Failed to parse extracted JSON: ${parseError.message}` + ); + log( + 'debug', + `Extracted JSON: ${extractedJson.substring(0, 500)}...` + ); + throw new Error( + `Gemini CLI returned invalid JSON that could not be parsed: ${parseError.message}` + ); + } + } + + return { + object: result.object, + usage: { + inputTokens: result.usage?.promptTokens, + outputTokens: result.usage?.completionTokens, + totalTokens: result.usage?.totalTokens + } + }; + } catch (retryError) { + log( + 'error', + `Gemini CLI manual JSON extraction failed: ${retryError.message}` + ); + // Re-throw the original error with more context + throw new Error( + `${this.name} failed to generate valid JSON object: ${error.message}` + ); + } + } + + // For non-parsing errors, just re-throw + throw error; + } + } +} diff --git a/src/ai-providers/index.js b/src/ai-providers/index.js index 9c1fd0b8..c0807533 100644 --- a/src/ai-providers/index.js +++ b/src/ai-providers/index.js @@ -14,3 +14,4 @@ export { BedrockAIProvider } from './bedrock.js'; export { AzureProvider } from './azure.js'; export { VertexAIProvider } from './google-vertex.js'; export { ClaudeCodeProvider } from './claude-code.js'; +export { GeminiCliProvider } from './gemini-cli.js'; diff --git a/src/constants/commands.js b/src/constants/commands.js new file mode 100644 index 00000000..6fdf56dc --- /dev/null +++ b/src/constants/commands.js @@ -0,0 +1,17 @@ +/** + * Command related constants + * Defines which commands trigger AI processing + */ + +// Command names that trigger AI processing +export const AI_COMMAND_NAMES = [ + 'add-task', + 'analyze-complexity', + 'expand-task', + 'parse-prd', + 'research', + 'research-save', + 'update-subtask', + 'update-task', + 'update-tasks' +]; diff --git a/src/constants/providers.js b/src/constants/providers.js index 18028e31..a683c6e8 100644 --- a/src/constants/providers.js +++ b/src/constants/providers.js @@ -20,7 +20,8 @@ export const CUSTOM_PROVIDERS = { BEDROCK: 'bedrock', OPENROUTER: 'openrouter', OLLAMA: 'ollama', - CLAUDE_CODE: 'claude-code' + CLAUDE_CODE: 'claude-code', + GEMINI_CLI: 'gemini-cli' }; // Custom providers array (for backward compatibility and iteration) diff --git a/src/utils/create-mcp-config.js b/src/utils/create-mcp-config.js index c630067f..d9db18e3 100644 --- a/src/utils/create-mcp-config.js +++ b/src/utils/create-mcp-config.js @@ -25,7 +25,7 @@ function formatJSONWithTabs(obj) { } // Structure matches project conventions (see scripts/init.js) -export function setupMCPConfiguration(projectDir, mcpConfigPath) { +export function setupMCPConfiguration(projectRoot, mcpConfigPath) { // Handle null mcpConfigPath (e.g., for Claude/Codex profiles) if (!mcpConfigPath) { log( @@ -36,7 +36,7 @@ export function setupMCPConfiguration(projectDir, mcpConfigPath) { } // Build the full path to the MCP config file - const mcpPath = path.join(projectDir, mcpConfigPath); + const mcpPath = path.join(projectRoot, mcpConfigPath); const configDir = path.dirname(mcpPath); log('info', `Setting up MCP configuration at ${mcpPath}...`); @@ -140,11 +140,11 @@ export function setupMCPConfiguration(projectDir, mcpConfigPath) { /** * Remove Task Master MCP server configuration from an existing mcp.json file * Only removes Task Master entries, preserving other MCP servers - * @param {string} projectDir - Target project directory + * @param {string} projectRoot - Target project directory * @param {string} mcpConfigPath - Relative path to MCP config file (e.g., '.cursor/mcp.json') * @returns {Object} Result object with success status and details */ -export function removeTaskMasterMCPConfiguration(projectDir, mcpConfigPath) { +export function removeTaskMasterMCPConfiguration(projectRoot, mcpConfigPath) { // Handle null mcpConfigPath (e.g., for Claude/Codex profiles) if (!mcpConfigPath) { return { @@ -156,7 +156,7 @@ export function removeTaskMasterMCPConfiguration(projectDir, mcpConfigPath) { }; } - const mcpPath = path.join(projectDir, mcpConfigPath); + const mcpPath = path.join(projectRoot, mcpConfigPath); let result = { success: false, diff --git a/src/utils/manage-gitignore.js b/src/utils/manage-gitignore.js index 25748bae..1f7db7ab 100644 --- a/src/utils/manage-gitignore.js +++ b/src/utils/manage-gitignore.js @@ -170,7 +170,7 @@ function validateInputs(targetPath, content, storeTasksInGit) { */ function createNewGitignoreFile(targetPath, templateLines, log) { try { - fs.writeFileSync(targetPath, templateLines.join('\n')); + fs.writeFileSync(targetPath, templateLines.join('\n') + '\n'); if (typeof log === 'function') { log('success', `Created ${targetPath} with full template`); } @@ -223,7 +223,7 @@ function mergeWithExistingFile( finalLines.push(...buildTaskFilesSection(storeTasksInGit)); // Write result - fs.writeFileSync(targetPath, finalLines.join('\n')); + fs.writeFileSync(targetPath, finalLines.join('\n') + '\n'); if (typeof log === 'function') { const hasNewContent = diff --git a/src/utils/path-utils.js b/src/utils/path-utils.js index 57853334..d764a235 100644 --- a/src/utils/path-utils.js +++ b/src/utils/path-utils.js @@ -25,6 +25,9 @@ import { getLoggerOrDefault } from './logger-utils.js'; export function normalizeProjectRoot(projectRoot) { if (!projectRoot) return projectRoot; + // Ensure it's a string + projectRoot = String(projectRoot); + // Split the path into segments const segments = projectRoot.split(path.sep); diff --git a/src/utils/rule-transformer.js b/src/utils/rule-transformer.js index d41a5505..2922fa2a 100644 --- a/src/utils/rule-transformer.js +++ b/src/utils/rule-transformer.js @@ -198,7 +198,7 @@ export function convertRuleToProfileRule(sourcePath, targetPath, profile) { /** * Convert all Cursor rules to profile rules for a specific profile */ -export function convertAllRulesToProfileRules(projectDir, profile) { +export function convertAllRulesToProfileRules(projectRoot, profile) { // Handle simple profiles (Claude, Codex) that just copy files to root const isSimpleProfile = Object.keys(profile.fileMap).length === 0; if (isSimpleProfile) { @@ -208,7 +208,7 @@ export function convertAllRulesToProfileRules(projectDir, profile) { const assetsDir = path.join(__dirname, '..', '..', 'assets'); if (typeof profile.onPostConvertRulesProfile === 'function') { - profile.onPostConvertRulesProfile(projectDir, assetsDir); + profile.onPostConvertRulesProfile(projectRoot, assetsDir); } return { success: 1, failed: 0 }; } @@ -216,7 +216,7 @@ export function convertAllRulesToProfileRules(projectDir, profile) { const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const sourceDir = path.join(__dirname, '..', '..', 'assets', 'rules'); - const targetDir = path.join(projectDir, profile.rulesDir); + const targetDir = path.join(projectRoot, profile.rulesDir); // Ensure target directory exists if (!fs.existsSync(targetDir)) { @@ -225,7 +225,7 @@ export function convertAllRulesToProfileRules(projectDir, profile) { // Setup MCP configuration if enabled if (profile.mcpConfig !== false) { - setupMCPConfiguration(projectDir, profile.mcpConfigPath); + setupMCPConfiguration(projectRoot, profile.mcpConfigPath); } let success = 0; @@ -286,7 +286,7 @@ export function convertAllRulesToProfileRules(projectDir, profile) { // Call post-processing hook if defined (e.g., for Roo's rules-*mode* folders) if (typeof profile.onPostConvertRulesProfile === 'function') { const assetsDir = path.join(__dirname, '..', '..', 'assets'); - profile.onPostConvertRulesProfile(projectDir, assetsDir); + profile.onPostConvertRulesProfile(projectRoot, assetsDir); } return { success, failed }; @@ -294,13 +294,13 @@ export function convertAllRulesToProfileRules(projectDir, profile) { /** * Remove only Task Master specific files from a profile, leaving other existing rules intact - * @param {string} projectDir - Target project directory + * @param {string} projectRoot - Target project directory * @param {Object} profile - Profile configuration * @returns {Object} Result object */ -export function removeProfileRules(projectDir, profile) { - const targetDir = path.join(projectDir, profile.rulesDir); - const profileDir = path.join(projectDir, profile.profileDir); +export function removeProfileRules(projectRoot, profile) { + const targetDir = path.join(projectRoot, profile.rulesDir); + const profileDir = path.join(projectRoot, profile.profileDir); const result = { profileName: profile.profileName, @@ -320,12 +320,12 @@ export function removeProfileRules(projectDir, profile) { if (isSimpleProfile) { // For simple profiles, just call their removal hook and return if (typeof profile.onRemoveRulesProfile === 'function') { - profile.onRemoveRulesProfile(projectDir); + profile.onRemoveRulesProfile(projectRoot); } result.success = true; log( 'debug', - `[Rule Transformer] Successfully removed ${profile.profileName} files from ${projectDir}` + `[Rule Transformer] Successfully removed ${profile.profileName} files from ${projectRoot}` ); return result; } @@ -418,7 +418,7 @@ export function removeProfileRules(projectDir, profile) { // 2. Handle MCP configuration - only remove Task Master, preserve other servers if (profile.mcpConfig !== false) { result.mcpResult = removeTaskMasterMCPConfiguration( - projectDir, + projectRoot, profile.mcpConfigPath ); if (result.mcpResult.hasOtherServers) { @@ -432,7 +432,7 @@ export function removeProfileRules(projectDir, profile) { // 3. Call removal hook if defined (e.g., Roo's custom cleanup) if (typeof profile.onRemoveRulesProfile === 'function') { - profile.onRemoveRulesProfile(projectDir); + profile.onRemoveRulesProfile(projectRoot); } // 4. Only remove profile directory if: @@ -490,7 +490,7 @@ export function removeProfileRules(projectDir, profile) { result.success = true; log( 'debug', - `[Rule Transformer] Successfully removed ${profile.profileName} Task Master files from ${projectDir}` + `[Rule Transformer] Successfully removed ${profile.profileName} Task Master files from ${projectRoot}` ); } catch (error) { result.error = error.message; diff --git a/tests/unit/ai-providers/gemini-cli.test.js b/tests/unit/ai-providers/gemini-cli.test.js new file mode 100644 index 00000000..cf0e08d8 --- /dev/null +++ b/tests/unit/ai-providers/gemini-cli.test.js @@ -0,0 +1,649 @@ +import { jest } from '@jest/globals'; + +// Mock the ai module +jest.unstable_mockModule('ai', () => ({ + generateObject: jest.fn(), + generateText: jest.fn(), + streamText: jest.fn() +})); + +// Mock the gemini-cli SDK module +jest.unstable_mockModule('ai-sdk-provider-gemini-cli', () => ({ + createGeminiProvider: jest.fn((options) => { + const provider = (modelId, settings) => ({ + // Mock language model + id: modelId, + settings, + authOptions: options + }); + provider.languageModel = jest.fn((id, settings) => ({ id, settings })); + provider.chat = provider.languageModel; + return provider; + }) +})); + +// Mock the base provider +jest.unstable_mockModule('../../../src/ai-providers/base-provider.js', () => ({ + BaseAIProvider: class { + constructor() { + this.name = 'Base Provider'; + } + handleError(context, error) { + throw error; + } + validateParams(params) { + // Basic validation + if (!params.modelId) { + throw new Error('Model ID is required'); + } + } + validateMessages(messages) { + if (!messages || !Array.isArray(messages)) { + throw new Error('Invalid messages array'); + } + } + async generateObject(params) { + // Mock implementation that can be overridden + throw new Error('Mock base generateObject error'); + } + } +})); + +// Mock the log module +jest.unstable_mockModule('../../../scripts/modules/index.js', () => ({ + log: jest.fn() +})); + +// Import after mocking +const { GeminiCliProvider } = await import( + '../../../src/ai-providers/gemini-cli.js' +); +const { createGeminiProvider } = await import('ai-sdk-provider-gemini-cli'); +const { generateObject, generateText, streamText } = await import('ai'); +const { log } = await import('../../../scripts/modules/index.js'); + +describe('GeminiCliProvider', () => { + let provider; + let consoleLogSpy; + + beforeEach(() => { + provider = new GeminiCliProvider(); + jest.clearAllMocks(); + consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(); + }); + + afterEach(() => { + consoleLogSpy.mockRestore(); + }); + + describe('constructor', () => { + it('should set the provider name to Gemini CLI', () => { + expect(provider.name).toBe('Gemini CLI'); + }); + }); + + describe('validateAuth', () => { + it('should not throw an error when API key is provided', () => { + expect(() => provider.validateAuth({ apiKey: 'test-key' })).not.toThrow(); + expect(consoleLogSpy).not.toHaveBeenCalled(); + }); + + it('should not require API key and should not log messages', () => { + expect(() => provider.validateAuth({})).not.toThrow(); + expect(consoleLogSpy).not.toHaveBeenCalled(); + }); + + it('should not require any parameters', () => { + expect(() => provider.validateAuth()).not.toThrow(); + expect(consoleLogSpy).not.toHaveBeenCalled(); + }); + }); + + describe('getClient', () => { + it('should return a gemini client with API key auth when apiKey is provided', async () => { + const client = await provider.getClient({ apiKey: 'test-api-key' }); + + expect(client).toBeDefined(); + expect(typeof client).toBe('function'); + expect(createGeminiProvider).toHaveBeenCalledWith({ + authType: 'api-key', + apiKey: 'test-api-key' + }); + }); + + it('should return a gemini client with OAuth auth when no apiKey is provided', async () => { + const client = await provider.getClient({}); + + expect(client).toBeDefined(); + expect(typeof client).toBe('function'); + expect(createGeminiProvider).toHaveBeenCalledWith({ + authType: 'oauth-personal' + }); + }); + + it('should include baseURL when provided', async () => { + const client = await provider.getClient({ + apiKey: 'test-key', + baseURL: 'https://custom-endpoint.com' + }); + + expect(client).toBeDefined(); + expect(createGeminiProvider).toHaveBeenCalledWith({ + authType: 'api-key', + apiKey: 'test-key', + baseURL: 'https://custom-endpoint.com' + }); + }); + + it('should have languageModel and chat methods', async () => { + const client = await provider.getClient({ apiKey: 'test-key' }); + expect(client.languageModel).toBeDefined(); + expect(client.chat).toBeDefined(); + expect(client.chat).toBe(client.languageModel); + }); + }); + + describe('_extractSystemMessage', () => { + it('should extract single system message', () => { + const messages = [ + { role: 'system', content: 'You are a helpful assistant' }, + { role: 'user', content: 'Hello' } + ]; + const result = provider._extractSystemMessage(messages); + expect(result.systemPrompt).toBe('You are a helpful assistant'); + expect(result.messages).toEqual([{ role: 'user', content: 'Hello' }]); + }); + + it('should combine multiple system messages', () => { + const messages = [ + { role: 'system', content: 'You are helpful' }, + { role: 'system', content: 'Be concise' }, + { role: 'user', content: 'Hello' } + ]; + const result = provider._extractSystemMessage(messages); + expect(result.systemPrompt).toBe('You are helpful\n\nBe concise'); + expect(result.messages).toEqual([{ role: 'user', content: 'Hello' }]); + }); + + it('should handle messages without system prompts', () => { + const messages = [ + { role: 'user', content: 'Hello' }, + { role: 'assistant', content: 'Hi there' } + ]; + const result = provider._extractSystemMessage(messages); + expect(result.systemPrompt).toBeUndefined(); + expect(result.messages).toEqual(messages); + }); + + it('should handle empty or invalid input', () => { + expect(provider._extractSystemMessage([])).toEqual({ + systemPrompt: undefined, + messages: [] + }); + expect(provider._extractSystemMessage(null)).toEqual({ + systemPrompt: undefined, + messages: [] + }); + expect(provider._extractSystemMessage(undefined)).toEqual({ + systemPrompt: undefined, + messages: [] + }); + }); + + it('should add JSON enforcement when enforceJsonOutput is true', () => { + const messages = [ + { role: 'system', content: 'You are a helpful assistant' }, + { role: 'user', content: 'Hello' } + ]; + const result = provider._extractSystemMessage(messages, { + enforceJsonOutput: true + }); + expect(result.systemPrompt).toContain('You are a helpful assistant'); + expect(result.systemPrompt).toContain( + 'CRITICAL: You MUST respond with ONLY valid JSON' + ); + expect(result.messages).toEqual([{ role: 'user', content: 'Hello' }]); + }); + + it('should add JSON enforcement with no existing system message', () => { + const messages = [{ role: 'user', content: 'Return JSON format' }]; + const result = provider._extractSystemMessage(messages, { + enforceJsonOutput: true + }); + expect(result.systemPrompt).toBe( + 'CRITICAL: You MUST respond with ONLY valid JSON. Do not include any explanatory text, markdown formatting, code block markers, or conversational phrases like "Here is" or "Of course". Your entire response must be parseable JSON that starts with { or [ and ends with } or ]. No exceptions.' + ); + expect(result.messages).toEqual([ + { role: 'user', content: 'Return JSON format' } + ]); + }); + }); + + describe('_detectJsonRequest', () => { + it('should detect JSON requests from user messages', () => { + const messages = [ + { + role: 'user', + content: 'Please return JSON format with subtasks array' + } + ]; + expect(provider._detectJsonRequest(messages)).toBe(true); + }); + + it('should detect various JSON indicators', () => { + const testCases = [ + 'respond only with valid JSON', + 'return JSON format', + 'output schema: {"test": true}', + 'format: [{"id": 1}]', + 'Please return subtasks in array format', + 'Return an object with properties' + ]; + + testCases.forEach((content) => { + const messages = [{ role: 'user', content }]; + expect(provider._detectJsonRequest(messages)).toBe(true); + }); + }); + + it('should not detect JSON requests for regular conversation', () => { + const messages = [{ role: 'user', content: 'Hello, how are you today?' }]; + expect(provider._detectJsonRequest(messages)).toBe(false); + }); + + it('should handle multiple user messages', () => { + const messages = [ + { role: 'user', content: 'Hello' }, + { role: 'assistant', content: 'Hi there' }, + { role: 'user', content: 'Now please return JSON format' } + ]; + expect(provider._detectJsonRequest(messages)).toBe(true); + }); + }); + + describe('_getJsonEnforcementPrompt', () => { + it('should return strict JSON enforcement prompt', () => { + const prompt = provider._getJsonEnforcementPrompt(); + expect(prompt).toContain('CRITICAL'); + expect(prompt).toContain('ONLY valid JSON'); + expect(prompt).toContain('No exceptions'); + }); + }); + + describe('_isValidJson', () => { + it('should return true for valid JSON objects', () => { + expect(provider._isValidJson('{"test": true}')).toBe(true); + expect(provider._isValidJson('{"subtasks": [{"id": 1}]}')).toBe(true); + }); + + it('should return true for valid JSON arrays', () => { + expect(provider._isValidJson('[1, 2, 3]')).toBe(true); + expect(provider._isValidJson('[{"id": 1}, {"id": 2}]')).toBe(true); + }); + + it('should return false for invalid JSON', () => { + expect(provider._isValidJson('Of course. Here is...')).toBe(false); + expect(provider._isValidJson('{"invalid": json}')).toBe(false); + expect(provider._isValidJson('not json at all')).toBe(false); + }); + + it('should handle edge cases', () => { + expect(provider._isValidJson('')).toBe(false); + expect(provider._isValidJson(null)).toBe(false); + expect(provider._isValidJson(undefined)).toBe(false); + expect(provider._isValidJson(' {"test": true} ')).toBe(true); // with whitespace + }); + }); + + describe('extractJson', () => { + it('should extract JSON from markdown code blocks', () => { + const input = '```json\n{"subtasks": [{"id": 1}]}\n```'; + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual({ subtasks: [{ id: 1 }] }); + }); + + it('should extract JSON with explanatory text', () => { + const input = 'Here\'s the JSON response:\n{"subtasks": [{"id": 1}]}'; + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual({ subtasks: [{ id: 1 }] }); + }); + + it('should handle variable declarations', () => { + const input = 'const result = {"subtasks": [{"id": 1}]};'; + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual({ subtasks: [{ id: 1 }] }); + }); + + it('should handle trailing commas with jsonc-parser', () => { + const input = '{"subtasks": [{"id": 1,}],}'; + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual({ subtasks: [{ id: 1 }] }); + }); + + it('should handle arrays', () => { + const input = 'The result is: [1, 2, 3]'; + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual([1, 2, 3]); + }); + + it('should handle nested objects with proper bracket matching', () => { + const input = + 'Response: {"outer": {"inner": {"value": "test"}}} extra text'; + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual({ outer: { inner: { value: 'test' } } }); + }); + + it('should handle escaped quotes in strings', () => { + const input = '{"message": "He said \\"hello\\" to me"}'; + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual({ message: 'He said "hello" to me' }); + }); + + it('should return original text if no JSON found', () => { + const input = 'No JSON here'; + expect(provider.extractJson(input)).toBe(input); + }); + + it('should handle null or non-string input', () => { + expect(provider.extractJson(null)).toBe(null); + expect(provider.extractJson(undefined)).toBe(undefined); + expect(provider.extractJson(123)).toBe(123); + }); + + it('should handle partial JSON by finding valid boundaries', () => { + const input = '{"valid": true, "partial": "incomplete'; + // Should return original text since no valid JSON can be extracted + expect(provider.extractJson(input)).toBe(input); + }); + + it('should handle performance edge cases with large text', () => { + // Test with large text that has JSON at the end + const largePrefix = 'This is a very long explanation. '.repeat(1000); + const json = '{"result": "success"}'; + const input = largePrefix + json; + + const result = provider.extractJson(input); + const parsed = JSON.parse(result); + expect(parsed).toEqual({ result: 'success' }); + }); + + it('should handle early termination for very large invalid content', () => { + // Test that it doesn't hang on very large content without JSON + const largeText = 'No JSON here. '.repeat(2000); + const result = provider.extractJson(largeText); + expect(result).toBe(largeText); + }); + }); + + describe('generateObject', () => { + const mockParams = { + modelId: 'gemini-2.0-flash-exp', + apiKey: 'test-key', + messages: [{ role: 'user', content: 'Test message' }], + schema: { type: 'object', properties: {} }, + objectName: 'testObject' + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should handle JSON parsing errors by attempting manual extraction', async () => { + // Mock the parent generateObject to throw a JSON parsing error + jest + .spyOn( + Object.getPrototypeOf(Object.getPrototypeOf(provider)), + 'generateObject' + ) + .mockRejectedValueOnce(new Error('Failed to parse JSON response')); + + // Mock generateObject from ai module to return text with JSON + generateObject.mockResolvedValueOnce({ + rawResponse: { + text: 'Here is the JSON:\n```json\n{"subtasks": [{"id": 1}]}\n```' + }, + object: null, + usage: { promptTokens: 10, completionTokens: 20, totalTokens: 30 } + }); + + const result = await provider.generateObject(mockParams); + + expect(log).toHaveBeenCalledWith( + 'debug', + expect.stringContaining('attempting manual extraction') + ); + expect(generateObject).toHaveBeenCalledWith({ + model: expect.objectContaining({ + id: 'gemini-2.0-flash-exp', + authOptions: expect.objectContaining({ + authType: 'api-key', + apiKey: 'test-key' + }) + }), + messages: mockParams.messages, + schema: mockParams.schema, + mode: 'json', // Should use json mode for Gemini + system: expect.stringContaining( + 'CRITICAL: You MUST respond with ONLY valid JSON' + ), + maxTokens: undefined, + temperature: undefined + }); + expect(result.object).toEqual({ subtasks: [{ id: 1 }] }); + }); + + it('should throw error if manual extraction also fails', async () => { + // Mock parent to throw JSON error + jest + .spyOn( + Object.getPrototypeOf(Object.getPrototypeOf(provider)), + 'generateObject' + ) + .mockRejectedValueOnce(new Error('Failed to parse JSON')); + + // Mock generateObject to return unparseable text + generateObject.mockResolvedValueOnce({ + rawResponse: { text: 'Not valid JSON at all' }, + object: null + }); + + await expect(provider.generateObject(mockParams)).rejects.toThrow( + 'Gemini CLI failed to generate valid JSON object: Failed to parse JSON' + ); + }); + + it('should pass through non-JSON errors unchanged', async () => { + const otherError = new Error('Network error'); + jest + .spyOn( + Object.getPrototypeOf(Object.getPrototypeOf(provider)), + 'generateObject' + ) + .mockRejectedValueOnce(otherError); + + await expect(provider.generateObject(mockParams)).rejects.toThrow( + 'Network error' + ); + expect(generateObject).not.toHaveBeenCalled(); + }); + + it('should handle successful response from parent', async () => { + const mockResult = { + object: { test: 'data' }, + usage: { inputTokens: 5, outputTokens: 10, totalTokens: 15 } + }; + jest + .spyOn( + Object.getPrototypeOf(Object.getPrototypeOf(provider)), + 'generateObject' + ) + .mockResolvedValueOnce(mockResult); + + const result = await provider.generateObject(mockParams); + expect(result).toEqual(mockResult); + expect(generateObject).not.toHaveBeenCalled(); + }); + }); + + describe('system message support', () => { + const mockParams = { + modelId: 'gemini-2.0-flash-exp', + apiKey: 'test-key', + messages: [ + { role: 'system', content: 'You are a helpful assistant' }, + { role: 'user', content: 'Hello' } + ], + maxTokens: 100, + temperature: 0.7 + }; + + describe('generateText with system messages', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should pass system prompt separately to AI SDK', async () => { + const { generateText } = await import('ai'); + generateText.mockResolvedValueOnce({ + text: 'Hello! How can I help you?', + usage: { promptTokens: 10, completionTokens: 8, totalTokens: 18 } + }); + + const result = await provider.generateText(mockParams); + + expect(generateText).toHaveBeenCalledWith({ + model: expect.objectContaining({ + id: 'gemini-2.0-flash-exp' + }), + system: 'You are a helpful assistant', + messages: [{ role: 'user', content: 'Hello' }], + maxTokens: 100, + temperature: 0.7 + }); + expect(result.text).toBe('Hello! How can I help you?'); + }); + + it('should handle messages without system prompt', async () => { + const { generateText } = await import('ai'); + const paramsNoSystem = { + ...mockParams, + messages: [{ role: 'user', content: 'Hello' }] + }; + + generateText.mockResolvedValueOnce({ + text: 'Hi there!', + usage: { promptTokens: 5, completionTokens: 3, totalTokens: 8 } + }); + + await provider.generateText(paramsNoSystem); + + expect(generateText).toHaveBeenCalledWith({ + model: expect.objectContaining({ + id: 'gemini-2.0-flash-exp' + }), + system: undefined, + messages: [{ role: 'user', content: 'Hello' }], + maxTokens: 100, + temperature: 0.7 + }); + }); + }); + + describe('streamText with system messages', () => { + it('should pass system prompt separately to AI SDK', async () => { + const { streamText } = await import('ai'); + const mockStream = { stream: 'mock-stream' }; + streamText.mockResolvedValueOnce(mockStream); + + const result = await provider.streamText(mockParams); + + expect(streamText).toHaveBeenCalledWith({ + model: expect.objectContaining({ + id: 'gemini-2.0-flash-exp' + }), + system: 'You are a helpful assistant', + messages: [{ role: 'user', content: 'Hello' }], + maxTokens: 100, + temperature: 0.7 + }); + expect(result).toBe(mockStream); + }); + }); + + describe('generateObject with system messages', () => { + const mockObjectParams = { + ...mockParams, + schema: { type: 'object', properties: {} }, + objectName: 'testObject' + }; + + it('should include system prompt in fallback generateObject call', async () => { + // Mock parent to throw JSON error + jest + .spyOn( + Object.getPrototypeOf(Object.getPrototypeOf(provider)), + 'generateObject' + ) + .mockRejectedValueOnce(new Error('Failed to parse JSON')); + + // Mock direct generateObject call + generateObject.mockResolvedValueOnce({ + object: { result: 'success' }, + usage: { promptTokens: 15, completionTokens: 10, totalTokens: 25 } + }); + + const result = await provider.generateObject(mockObjectParams); + + expect(generateObject).toHaveBeenCalledWith({ + model: expect.objectContaining({ + id: 'gemini-2.0-flash-exp' + }), + system: expect.stringContaining('You are a helpful assistant'), + messages: [{ role: 'user', content: 'Hello' }], + schema: mockObjectParams.schema, + mode: 'json', + maxTokens: 100, + temperature: 0.7 + }); + expect(result.object).toEqual({ result: 'success' }); + }); + }); + }); + + // Note: Error handling for module loading is tested in integration tests + // since dynamic imports are difficult to mock properly in unit tests + + describe('authentication scenarios', () => { + it('should use api-key auth type with API key', async () => { + await provider.getClient({ apiKey: 'gemini-test-key' }); + + expect(createGeminiProvider).toHaveBeenCalledWith({ + authType: 'api-key', + apiKey: 'gemini-test-key' + }); + }); + + it('should use oauth-personal auth type without API key', async () => { + await provider.getClient({}); + + expect(createGeminiProvider).toHaveBeenCalledWith({ + authType: 'oauth-personal' + }); + }); + + it('should handle empty string API key as no API key', async () => { + await provider.getClient({ apiKey: '' }); + + expect(createGeminiProvider).toHaveBeenCalledWith({ + authType: 'oauth-personal' + }); + }); + }); +}); diff --git a/tests/unit/ai-services-unified.test.js b/tests/unit/ai-services-unified.test.js index 74292123..f12b37bf 100644 --- a/tests/unit/ai-services-unified.test.js +++ b/tests/unit/ai-services-unified.test.js @@ -8,6 +8,7 @@ const mockGetResearchModelId = jest.fn(); const mockGetFallbackProvider = jest.fn(); const mockGetFallbackModelId = jest.fn(); const mockGetParametersForRole = jest.fn(); +const mockGetResponseLanguage = jest.fn(); const mockGetUserId = jest.fn(); const mockGetDebugFlag = jest.fn(); const mockIsApiKeySet = jest.fn(); @@ -98,6 +99,7 @@ jest.unstable_mockModule('../../scripts/modules/config-manager.js', () => ({ getFallbackMaxTokens: mockGetFallbackMaxTokens, getFallbackTemperature: mockGetFallbackTemperature, getParametersForRole: mockGetParametersForRole, + getResponseLanguage: mockGetResponseLanguage, getUserId: mockGetUserId, getDebugFlag: mockGetDebugFlag, getBaseUrlForRole: mockGetBaseUrlForRole, @@ -117,7 +119,10 @@ jest.unstable_mockModule('../../scripts/modules/config-manager.js', () => ({ getBedrockBaseURL: mockGetBedrockBaseURL, getVertexProjectId: mockGetVertexProjectId, getVertexLocation: mockGetVertexLocation, - getMcpApiKeyStatus: mockGetMcpApiKeyStatus + getMcpApiKeyStatus: mockGetMcpApiKeyStatus, + + // Providers without API keys + providersWithoutApiKeys: ['ollama', 'bedrock', 'gemini-cli'] })); // Mock AI Provider Classes with proper methods @@ -185,6 +190,11 @@ jest.unstable_mockModule('../../src/ai-providers/index.js', () => ({ generateText: jest.fn(), streamText: jest.fn(), generateObject: jest.fn() + })), + GeminiCliProvider: jest.fn(() => ({ + generateText: jest.fn(), + streamText: jest.fn(), + generateObject: jest.fn() })) })); @@ -269,6 +279,7 @@ describe('Unified AI Services', () => { if (role === 'fallback') return { maxTokens: 150, temperature: 0.6 }; return { maxTokens: 100, temperature: 0.5 }; // Default }); + mockGetResponseLanguage.mockReturnValue('English'); mockResolveEnvVariable.mockImplementation((key) => { if (key === 'ANTHROPIC_API_KEY') return 'mock-anthropic-key'; if (key === 'PERPLEXITY_API_KEY') return 'mock-perplexity-key'; @@ -455,6 +466,68 @@ describe('Unified AI Services', () => { expect(mockAnthropicProvider.generateText).toHaveBeenCalledTimes(1); }); + test('should use configured responseLanguage in system prompt', async () => { + mockGetResponseLanguage.mockReturnValue('中文'); + mockAnthropicProvider.generateText.mockResolvedValue('中文回复'); + + const params = { + role: 'main', + systemPrompt: 'You are an assistant', + prompt: 'Hello' + }; + await generateTextService(params); + + expect(mockAnthropicProvider.generateText).toHaveBeenCalledWith( + expect.objectContaining({ + messages: [ + { + role: 'system', + content: expect.stringContaining('Always respond in 中文') + }, + { role: 'user', content: 'Hello' } + ] + }) + ); + expect(mockGetResponseLanguage).toHaveBeenCalledWith(fakeProjectRoot); + }); + + test('should pass custom projectRoot to getResponseLanguage', async () => { + const customRoot = '/custom/project/root'; + mockGetResponseLanguage.mockReturnValue('Español'); + mockAnthropicProvider.generateText.mockResolvedValue( + 'Respuesta en Español' + ); + + const params = { + role: 'main', + systemPrompt: 'You are an assistant', + prompt: 'Hello', + projectRoot: customRoot + }; + await generateTextService(params); + + expect(mockGetResponseLanguage).toHaveBeenCalledWith(customRoot); + expect(mockAnthropicProvider.generateText).toHaveBeenCalledWith( + expect.objectContaining({ + messages: [ + { + role: 'system', + content: expect.stringContaining('Always respond in Español') + }, + { role: 'user', content: 'Hello' } + ] + }) + ); + }); + + // Add more tests for edge cases: + // - Missing API keys (should throw from _resolveApiKey) + // - Unsupported provider configured (should skip and log) + // - Missing provider/model config for a role (should skip and log) + // - Missing prompt + // - Different initial roles (research, fallback) + // - generateObjectService (mock schema, check object result) + // - streamTextService (more complex to test, might need stream helpers) test('should skip provider with missing API key and try next in fallback sequence', async () => { // Setup isApiKeySet to return false for anthropic but true for perplexity mockIsApiKeySet.mockImplementation((provider, session, root) => { diff --git a/tests/unit/config-manager.test.js b/tests/unit/config-manager.test.js index 8d4fd803..a0f315a3 100644 --- a/tests/unit/config-manager.test.js +++ b/tests/unit/config-manager.test.js @@ -48,11 +48,14 @@ const mockConsole = { }; global.console = mockConsole; +// --- Define Mock Function Instances --- +const mockFindConfigPath = jest.fn(() => null); // Default to null, can be overridden in tests + // Mock path-utils to prevent config file path discovery and logging jest.mock('../../src/utils/path-utils.js', () => ({ __esModule: true, findProjectRoot: jest.fn(() => '/mock/project'), - findConfigPath: jest.fn(() => null), // Always return null to prevent config discovery + findConfigPath: mockFindConfigPath, // Use the mock function instance findTasksPath: jest.fn(() => '/mock/tasks.json'), findComplexityReportPath: jest.fn(() => null), resolveTasksOutputPath: jest.fn(() => '/mock/tasks.json'), @@ -136,12 +139,15 @@ const DEFAULT_CONFIG = { global: { logLevel: 'info', debug: false, + defaultNumTasks: 10, defaultSubtasks: 5, defaultPriority: 'medium', projectName: 'Task Master', ollamaBaseURL: 'http://localhost:11434/api', - bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com' - } + bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com', + responseLanguage: 'English' + }, + claudeCode: {} }; // Other test data (VALID_CUSTOM_CONFIG, PARTIAL_CONFIG, INVALID_PROVIDER_CONFIG) @@ -195,6 +201,61 @@ const INVALID_PROVIDER_CONFIG = { } }; +// Claude Code test data +const VALID_CLAUDE_CODE_CONFIG = { + maxTurns: 5, + customSystemPrompt: 'You are a helpful coding assistant', + appendSystemPrompt: 'Always follow best practices', + permissionMode: 'acceptEdits', + allowedTools: ['Read', 'LS', 'Edit'], + disallowedTools: ['Write'], + mcpServers: { + 'test-server': { + type: 'stdio', + command: 'node', + args: ['server.js'], + env: { NODE_ENV: 'test' } + } + }, + commandSpecific: { + 'add-task': { + maxTurns: 3, + permissionMode: 'plan' + }, + research: { + customSystemPrompt: 'You are a research assistant' + } + } +}; + +const INVALID_CLAUDE_CODE_CONFIG = { + maxTurns: 'invalid', // Should be number + permissionMode: 'invalid-mode', // Invalid enum value + allowedTools: 'not-an-array', // Should be array + mcpServers: { + 'invalid-server': { + type: 'invalid-type', // Invalid enum value + url: 'not-a-valid-url' // Invalid URL format + } + }, + commandSpecific: { + 'invalid-command': { + // Invalid command name + maxTurns: -1 // Invalid negative number + } + } +}; + +const PARTIAL_CLAUDE_CODE_CONFIG = { + maxTurns: 10, + permissionMode: 'default', + commandSpecific: { + 'expand-task': { + customSystemPrompt: 'Focus on task breakdown' + } + } +}; + // Define spies globally to be restored in afterAll let consoleErrorSpy; let consoleWarnSpy; @@ -220,6 +281,7 @@ beforeEach(() => { // Reset the external mock instances for utils mockFindProjectRoot.mockReset(); mockLog.mockReset(); + mockFindConfigPath.mockReset(); // --- Set up spies ON the imported 'fs' mock --- fsExistsSyncSpy = jest.spyOn(fsMocked, 'existsSync'); @@ -228,6 +290,7 @@ beforeEach(() => { // --- Default Mock Implementations --- mockFindProjectRoot.mockReturnValue(MOCK_PROJECT_ROOT); // Default for utils.findProjectRoot + mockFindConfigPath.mockReturnValue(null); // Default to no config file found fsExistsSyncSpy.mockReturnValue(true); // Assume files exist by default // Default readFileSync: Return REAL models content, mocked config, or throw error @@ -325,6 +388,162 @@ describe('Validation Functions', () => { }); }); +// --- Claude Code Validation Tests --- +describe('Claude Code Validation', () => { + test('validateClaudeCodeSettings should return valid settings for correct input', () => { + const result = configManager.validateClaudeCodeSettings( + VALID_CLAUDE_CODE_CONFIG + ); + + expect(result).toEqual(VALID_CLAUDE_CODE_CONFIG); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('validateClaudeCodeSettings should return empty object for invalid input', () => { + const result = configManager.validateClaudeCodeSettings( + INVALID_CLAUDE_CODE_CONFIG + ); + + expect(result).toEqual({}); + expect(consoleWarnSpy).toHaveBeenCalledWith( + expect.stringContaining('Warning: Invalid Claude Code settings in config') + ); + }); + + test('validateClaudeCodeSettings should handle partial valid configuration', () => { + const result = configManager.validateClaudeCodeSettings( + PARTIAL_CLAUDE_CODE_CONFIG + ); + + expect(result).toEqual(PARTIAL_CLAUDE_CODE_CONFIG); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('validateClaudeCodeSettings should return empty object for empty input', () => { + const result = configManager.validateClaudeCodeSettings({}); + + expect(result).toEqual({}); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('validateClaudeCodeSettings should handle null/undefined input', () => { + expect(configManager.validateClaudeCodeSettings(null)).toEqual({}); + expect(configManager.validateClaudeCodeSettings(undefined)).toEqual({}); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + }); +}); + +// --- Claude Code Getter Tests --- +describe('Claude Code Getter Functions', () => { + test('getClaudeCodeSettings should return default empty object when no config exists', () => { + // No config file exists, should return empty object + fsExistsSyncSpy.mockReturnValue(false); + const settings = configManager.getClaudeCodeSettings(MOCK_PROJECT_ROOT); + + expect(settings).toEqual({}); + }); + + test('getClaudeCodeSettings should return merged settings from config file', () => { + // Config file with Claude Code settings + const configWithClaudeCode = { + ...VALID_CUSTOM_CONFIG, + claudeCode: VALID_CLAUDE_CODE_CONFIG + }; + + // Mock findConfigPath to return the mock config path + mockFindConfigPath.mockReturnValue(MOCK_CONFIG_PATH); + + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (filePath === MOCK_CONFIG_PATH) + return JSON.stringify(configWithClaudeCode); + if (path.basename(filePath) === 'supported-models.json') { + return JSON.stringify({ + openai: [{ id: 'gpt-4o' }], + google: [{ id: 'gemini-1.5-pro-latest' }], + anthropic: [ + { id: 'claude-3-opus-20240229' }, + { id: 'claude-3-7-sonnet-20250219' }, + { id: 'claude-3-5-sonnet' } + ], + perplexity: [{ id: 'sonar-pro' }], + ollama: [], + openrouter: [] + }); + } + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + fsExistsSyncSpy.mockReturnValue(true); + + const settings = configManager.getClaudeCodeSettings( + MOCK_PROJECT_ROOT, + true + ); // Force reload + + expect(settings).toEqual(VALID_CLAUDE_CODE_CONFIG); + }); + + test('getClaudeCodeSettingsForCommand should return command-specific settings', () => { + // Config with command-specific settings + const configWithClaudeCode = { + ...VALID_CUSTOM_CONFIG, + claudeCode: VALID_CLAUDE_CODE_CONFIG + }; + + // Mock findConfigPath to return the mock config path + mockFindConfigPath.mockReturnValue(MOCK_CONFIG_PATH); + + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (path.basename(filePath) === 'supported-models.json') return '{}'; + if (filePath === MOCK_CONFIG_PATH) + return JSON.stringify(configWithClaudeCode); + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + fsExistsSyncSpy.mockReturnValue(true); + + const settings = configManager.getClaudeCodeSettingsForCommand( + 'add-task', + MOCK_PROJECT_ROOT, + true + ); // Force reload + + // Should merge global settings with command-specific settings + const expectedSettings = { + ...VALID_CLAUDE_CODE_CONFIG, + ...VALID_CLAUDE_CODE_CONFIG.commandSpecific['add-task'] + }; + expect(settings).toEqual(expectedSettings); + }); + + test('getClaudeCodeSettingsForCommand should return global settings for unknown command', () => { + // Config with Claude Code settings + const configWithClaudeCode = { + ...VALID_CUSTOM_CONFIG, + claudeCode: PARTIAL_CLAUDE_CODE_CONFIG + }; + + // Mock findConfigPath to return the mock config path + mockFindConfigPath.mockReturnValue(MOCK_CONFIG_PATH); + + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (path.basename(filePath) === 'supported-models.json') return '{}'; + if (filePath === MOCK_CONFIG_PATH) + return JSON.stringify(configWithClaudeCode); + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + fsExistsSyncSpy.mockReturnValue(true); + + const settings = configManager.getClaudeCodeSettingsForCommand( + 'unknown-command', + MOCK_PROJECT_ROOT, + true + ); // Force reload + + // Should return global settings only + expect(settings).toEqual(PARTIAL_CLAUDE_CODE_CONFIG); + }); +}); + // --- getConfig Tests --- describe('getConfig Tests', () => { test('should return default config if .taskmasterconfig does not exist', () => { @@ -409,7 +628,11 @@ describe('getConfig Tests', () => { ...VALID_CUSTOM_CONFIG.models.fallback } }, - global: { ...DEFAULT_CONFIG.global, ...VALID_CUSTOM_CONFIG.global } + global: { ...DEFAULT_CONFIG.global, ...VALID_CUSTOM_CONFIG.global }, + claudeCode: { + ...DEFAULT_CONFIG.claudeCode, + ...VALID_CUSTOM_CONFIG.claudeCode + } }; expect(config).toEqual(expectedMergedConfig); expect(fsExistsSyncSpy).toHaveBeenCalledWith(MOCK_CONFIG_PATH); @@ -447,7 +670,11 @@ describe('getConfig Tests', () => { research: { ...DEFAULT_CONFIG.models.research }, fallback: { ...DEFAULT_CONFIG.models.fallback } }, - global: { ...DEFAULT_CONFIG.global, ...PARTIAL_CONFIG.global } + global: { ...DEFAULT_CONFIG.global, ...PARTIAL_CONFIG.global }, + claudeCode: { + ...DEFAULT_CONFIG.claudeCode, + ...VALID_CUSTOM_CONFIG.claudeCode + } }; expect(config).toEqual(expectedMergedConfig); expect(fsReadFileSyncSpy).toHaveBeenCalledWith(MOCK_CONFIG_PATH, 'utf-8'); @@ -551,7 +778,11 @@ describe('getConfig Tests', () => { }, fallback: { ...DEFAULT_CONFIG.models.fallback } }, - global: { ...DEFAULT_CONFIG.global, ...INVALID_PROVIDER_CONFIG.global } + global: { ...DEFAULT_CONFIG.global, ...INVALID_PROVIDER_CONFIG.global }, + claudeCode: { + ...DEFAULT_CONFIG.claudeCode, + ...VALID_CUSTOM_CONFIG.claudeCode + } }; expect(config).toEqual(expectedMergedConfig); }); @@ -684,6 +915,82 @@ describe('Getter Functions', () => { expect(logLevel).toBe(VALID_CUSTOM_CONFIG.global.logLevel); }); + test('getResponseLanguage should return responseLanguage from config', () => { + // Arrange + // Prepare a config object with responseLanguage property for this test + const configWithLanguage = JSON.stringify({ + models: { + main: { provider: 'openai', modelId: 'gpt-4-turbo' } + }, + global: { + projectName: 'Test Project', + responseLanguage: '中文' + } + }); + + // Set up fs.readFileSync to return our test config + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (filePath === MOCK_CONFIG_PATH) { + return configWithLanguage; + } + if (path.basename(filePath) === 'supported-models.json') { + return JSON.stringify({ + openai: [{ id: 'gpt-4-turbo' }] + }); + } + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + + fsExistsSyncSpy.mockReturnValue(true); + + // Ensure getConfig returns new values instead of cached ones + configManager.getConfig(MOCK_PROJECT_ROOT, true); + + // Act + const responseLanguage = + configManager.getResponseLanguage(MOCK_PROJECT_ROOT); + + // Assert + expect(responseLanguage).toBe('中文'); + }); + + test('getResponseLanguage should return undefined when responseLanguage is not in config', () => { + // Arrange + const configWithoutLanguage = JSON.stringify({ + models: { + main: { provider: 'openai', modelId: 'gpt-4-turbo' } + }, + global: { + projectName: 'Test Project' + // No responseLanguage property + } + }); + + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (filePath === MOCK_CONFIG_PATH) { + return configWithoutLanguage; + } + if (path.basename(filePath) === 'supported-models.json') { + return JSON.stringify({ + openai: [{ id: 'gpt-4-turbo' }] + }); + } + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + + fsExistsSyncSpy.mockReturnValue(true); + + // Ensure getConfig returns new values instead of cached ones + configManager.getConfig(MOCK_PROJECT_ROOT, true); + + // Act + const responseLanguage = + configManager.getResponseLanguage(MOCK_PROJECT_ROOT); + + // Assert + expect(responseLanguage).toBe('English'); + }); + // Add more tests for other getters (getResearchProvider, getProjectName, etc.) }); @@ -738,5 +1045,116 @@ describe('getAllProviders', () => { // Add tests for getParametersForRole if needed +// --- defaultNumTasks Tests --- +describe('Configuration Getters', () => { + test('getDefaultNumTasks should return default value when config is valid', () => { + // Arrange: Mock fs.readFileSync to return valid config when called with the expected path + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (filePath === MOCK_CONFIG_PATH) { + return JSON.stringify({ + global: { + defaultNumTasks: 15 + } + }); + } + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + fsExistsSyncSpy.mockReturnValue(true); + + // Force reload to clear cache + configManager.getConfig(MOCK_PROJECT_ROOT, true); + + // Act: Call getDefaultNumTasks with explicit root + const result = configManager.getDefaultNumTasks(MOCK_PROJECT_ROOT); + + // Assert + expect(result).toBe(15); + }); + + test('getDefaultNumTasks should return fallback when config value is invalid', () => { + // Arrange: Mock fs.readFileSync to return invalid config + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (filePath === MOCK_CONFIG_PATH) { + return JSON.stringify({ + global: { + defaultNumTasks: 'invalid' + } + }); + } + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + fsExistsSyncSpy.mockReturnValue(true); + + // Force reload to clear cache + configManager.getConfig(MOCK_PROJECT_ROOT, true); + + // Act: Call getDefaultNumTasks with explicit root + const result = configManager.getDefaultNumTasks(MOCK_PROJECT_ROOT); + + // Assert + expect(result).toBe(10); // Should fallback to DEFAULTS.global.defaultNumTasks + }); + + test('getDefaultNumTasks should return fallback when config value is missing', () => { + // Arrange: Mock fs.readFileSync to return config without defaultNumTasks + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (filePath === MOCK_CONFIG_PATH) { + return JSON.stringify({ + global: {} + }); + } + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + fsExistsSyncSpy.mockReturnValue(true); + + // Force reload to clear cache + configManager.getConfig(MOCK_PROJECT_ROOT, true); + + // Act: Call getDefaultNumTasks with explicit root + const result = configManager.getDefaultNumTasks(MOCK_PROJECT_ROOT); + + // Assert + expect(result).toBe(10); // Should fallback to DEFAULTS.global.defaultNumTasks + }); + + test('getDefaultNumTasks should handle non-existent config file', () => { + // Arrange: Mock file not existing + fsExistsSyncSpy.mockReturnValue(false); + + // Force reload to clear cache + configManager.getConfig(MOCK_PROJECT_ROOT, true); + + // Act: Call getDefaultNumTasks with explicit root + const result = configManager.getDefaultNumTasks(MOCK_PROJECT_ROOT); + + // Assert + expect(result).toBe(10); // Should fallback to DEFAULTS.global.defaultNumTasks + }); + + test('getDefaultNumTasks should accept explicit project root', () => { + // Arrange: Mock fs.readFileSync to return valid config + fsReadFileSyncSpy.mockImplementation((filePath) => { + if (filePath === MOCK_CONFIG_PATH) { + return JSON.stringify({ + global: { + defaultNumTasks: 20 + } + }); + } + throw new Error(`Unexpected fs.readFileSync call: ${filePath}`); + }); + fsExistsSyncSpy.mockReturnValue(true); + + // Force reload to clear cache + configManager.getConfig(MOCK_PROJECT_ROOT, true); + + // Act: Call getDefaultNumTasks with explicit project root + const result = configManager.getDefaultNumTasks(MOCK_PROJECT_ROOT); + + // Assert + expect(result).toBe(20); + }); +}); + // Note: Tests for setMainModel, setResearchModel were removed as the functions were removed in the implementation. // If similar setter functions exist, add tests for them following the writeConfig pattern. diff --git a/tests/unit/manage-gitignore.test.js b/tests/unit/manage-gitignore.test.js index e92274be..61526915 100644 --- a/tests/unit/manage-gitignore.test.js +++ b/tests/unit/manage-gitignore.test.js @@ -179,7 +179,8 @@ logs # Task files # tasks.json -# tasks/ ` +# tasks/ +` ); expect(mockLog).toHaveBeenCalledWith( 'success', @@ -200,7 +201,8 @@ logs # Task files tasks.json -tasks/ ` +tasks/ +` ); expect(mockLog).toHaveBeenCalledWith( 'success', @@ -432,7 +434,8 @@ tasks/ `; const writtenContent = writeFileSyncSpy.mock.calls[0][1]; expect(writtenContent).toBe(`# Task files # tasks.json -# tasks/ `); +# tasks/ +`); }); }); }); diff --git a/tests/unit/mcp/tools/remove-task.test.js b/tests/unit/mcp/tools/remove-task.test.js new file mode 100644 index 00000000..0568f183 --- /dev/null +++ b/tests/unit/mcp/tools/remove-task.test.js @@ -0,0 +1,528 @@ +/** + * Tests for the remove-task MCP tool + * + * Note: This test does NOT test the actual implementation. It tests that: + * 1. The tool is registered correctly with the correct parameters + * 2. Arguments are passed correctly to removeTaskDirect + * 3. Error handling works as expected + * 4. Tag parameter is properly handled and passed through + * + * We do NOT import the real implementation - everything is mocked + */ + +import { jest } from '@jest/globals'; + +// Mock EVERYTHING +const mockRemoveTaskDirect = jest.fn(); +jest.mock('../../../../mcp-server/src/core/task-master-core.js', () => ({ + removeTaskDirect: mockRemoveTaskDirect +})); + +const mockHandleApiResult = jest.fn((result) => result); +const mockWithNormalizedProjectRoot = jest.fn((fn) => fn); +const mockCreateErrorResponse = jest.fn((msg) => ({ + success: false, + error: { code: 'ERROR', message: msg } +})); +const mockFindTasksPath = jest.fn(() => '/mock/project/tasks.json'); + +jest.mock('../../../../mcp-server/src/tools/utils.js', () => ({ + handleApiResult: mockHandleApiResult, + createErrorResponse: mockCreateErrorResponse, + withNormalizedProjectRoot: mockWithNormalizedProjectRoot +})); + +jest.mock('../../../../mcp-server/src/core/utils/path-utils.js', () => ({ + findTasksPath: mockFindTasksPath +})); + +// Mock the z object from zod +const mockZod = { + object: jest.fn(() => mockZod), + string: jest.fn(() => mockZod), + boolean: jest.fn(() => mockZod), + optional: jest.fn(() => mockZod), + describe: jest.fn(() => mockZod), + _def: { + shape: () => ({ + id: {}, + file: {}, + projectRoot: {}, + confirm: {}, + tag: {} + }) + } +}; + +jest.mock('zod', () => ({ + z: mockZod +})); + +// DO NOT import the real module - create a fake implementation +// This is the fake implementation of registerRemoveTaskTool +const registerRemoveTaskTool = (server) => { + // Create simplified version of the tool config + const toolConfig = { + name: 'remove_task', + description: 'Remove a task or subtask permanently from the tasks list', + parameters: mockZod, + + // Create a simplified mock of the execute function + execute: mockWithNormalizedProjectRoot(async (args, context) => { + const { log, session } = context; + + try { + log.info && log.info(`Removing task(s) with ID(s): ${args.id}`); + + // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) + let tasksJsonPath; + try { + tasksJsonPath = mockFindTasksPath( + { projectRoot: args.projectRoot, file: args.file }, + log + ); + } catch (error) { + log.error && log.error(`Error finding tasks.json: ${error.message}`); + return mockCreateErrorResponse( + `Failed to find tasks.json: ${error.message}` + ); + } + + log.info && log.info(`Using tasks file path: ${tasksJsonPath}`); + + const result = await mockRemoveTaskDirect( + { + tasksJsonPath: tasksJsonPath, + id: args.id, + projectRoot: args.projectRoot, + tag: args.tag + }, + log, + { session } + ); + + if (result.success) { + log.info && log.info(`Successfully removed task: ${args.id}`); + } else { + log.error && + log.error(`Failed to remove task: ${result.error.message}`); + } + + return mockHandleApiResult( + result, + log, + 'Error removing task', + undefined, + args.projectRoot + ); + } catch (error) { + log.error && log.error(`Error in remove-task tool: ${error.message}`); + return mockCreateErrorResponse(error.message); + } + }) + }; + + // Register the tool with the server + server.addTool(toolConfig); +}; + +describe('MCP Tool: remove-task', () => { + // Create mock server + let mockServer; + let executeFunction; + + // Create mock logger + const mockLogger = { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn() + }; + + // Test data + const validArgs = { + id: '5', + projectRoot: '/mock/project/root', + file: '/mock/project/tasks.json', + confirm: true, + tag: 'feature-branch' + }; + + const multipleTaskArgs = { + id: '5,6.1,7', + projectRoot: '/mock/project/root', + tag: 'master' + }; + + // Standard responses + const successResponse = { + success: true, + data: { + totalTasks: 1, + successful: 1, + failed: 0, + removedTasks: [ + { + id: 5, + title: 'Removed Task', + status: 'pending' + } + ], + messages: ["Successfully removed task 5 from tag 'feature-branch'"], + errors: [], + tasksPath: '/mock/project/tasks.json', + tag: 'feature-branch' + } + }; + + const multipleTasksSuccessResponse = { + success: true, + data: { + totalTasks: 3, + successful: 3, + failed: 0, + removedTasks: [ + { id: 5, title: 'Task 5', status: 'pending' }, + { id: 1, title: 'Subtask 6.1', status: 'done', parentTaskId: 6 }, + { id: 7, title: 'Task 7', status: 'in-progress' } + ], + messages: [ + "Successfully removed task 5 from tag 'master'", + "Successfully removed subtask 6.1 from tag 'master'", + "Successfully removed task 7 from tag 'master'" + ], + errors: [], + tasksPath: '/mock/project/tasks.json', + tag: 'master' + } + }; + + const errorResponse = { + success: false, + error: { + code: 'INVALID_TASK_ID', + message: "The following tasks were not found in tag 'feature-branch': 999" + } + }; + + const pathErrorResponse = { + success: false, + error: { + code: 'PATH_ERROR', + message: 'Failed to find tasks.json: No tasks.json found' + } + }; + + beforeEach(() => { + // Reset all mocks + jest.clearAllMocks(); + + // Create mock server + mockServer = { + addTool: jest.fn((config) => { + executeFunction = config.execute; + }) + }; + + // Setup default successful response + mockRemoveTaskDirect.mockResolvedValue(successResponse); + mockFindTasksPath.mockReturnValue('/mock/project/tasks.json'); + + // Register the tool + registerRemoveTaskTool(mockServer); + }); + + test('should register the tool correctly', () => { + // Verify tool was registered + expect(mockServer.addTool).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'remove_task', + description: 'Remove a task or subtask permanently from the tasks list', + parameters: expect.any(Object), + execute: expect.any(Function) + }) + ); + + // Verify the tool config was passed + const toolConfig = mockServer.addTool.mock.calls[0][0]; + expect(toolConfig).toHaveProperty('parameters'); + expect(toolConfig).toHaveProperty('execute'); + }); + + test('should execute the tool with valid parameters including tag', async () => { + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + await executeFunction(validArgs, mockContext); + + // Verify findTasksPath was called with correct arguments + expect(mockFindTasksPath).toHaveBeenCalledWith( + { + projectRoot: validArgs.projectRoot, + file: validArgs.file + }, + mockLogger + ); + + // Verify removeTaskDirect was called with correct arguments including tag + expect(mockRemoveTaskDirect).toHaveBeenCalledWith( + expect.objectContaining({ + tasksJsonPath: '/mock/project/tasks.json', + id: validArgs.id, + projectRoot: validArgs.projectRoot, + tag: validArgs.tag // This is the key test - tag parameter should be passed through + }), + mockLogger, + { + session: mockContext.session + } + ); + + // Verify handleApiResult was called + expect(mockHandleApiResult).toHaveBeenCalledWith( + successResponse, + mockLogger, + 'Error removing task', + undefined, + validArgs.projectRoot + ); + }); + + test('should handle multiple task IDs with tag context', async () => { + // Setup multiple tasks response + mockRemoveTaskDirect.mockResolvedValueOnce(multipleTasksSuccessResponse); + + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + await executeFunction(multipleTaskArgs, mockContext); + + // Verify removeTaskDirect was called with comma-separated IDs and tag + expect(mockRemoveTaskDirect).toHaveBeenCalledWith( + expect.objectContaining({ + id: '5,6.1,7', + tag: 'master' + }), + mockLogger, + expect.any(Object) + ); + + // Verify successful handling of multiple tasks + expect(mockHandleApiResult).toHaveBeenCalledWith( + multipleTasksSuccessResponse, + mockLogger, + 'Error removing task', + undefined, + multipleTaskArgs.projectRoot + ); + }); + + test('should handle missing tag parameter (defaults to current tag)', async () => { + const argsWithoutTag = { + id: '5', + projectRoot: '/mock/project/root' + }; + + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + await executeFunction(argsWithoutTag, mockContext); + + // Verify removeTaskDirect was called with undefined tag (should default to current tag) + expect(mockRemoveTaskDirect).toHaveBeenCalledWith( + expect.objectContaining({ + id: '5', + projectRoot: '/mock/project/root', + tag: undefined // Should be undefined when not provided + }), + mockLogger, + expect.any(Object) + ); + }); + + test('should handle errors from removeTaskDirect', async () => { + // Setup error response + mockRemoveTaskDirect.mockResolvedValueOnce(errorResponse); + + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + await executeFunction(validArgs, mockContext); + + // Verify removeTaskDirect was called + expect(mockRemoveTaskDirect).toHaveBeenCalled(); + + // Verify error logging + expect(mockLogger.error).toHaveBeenCalledWith( + "Failed to remove task: The following tasks were not found in tag 'feature-branch': 999" + ); + + // Verify handleApiResult was called with error response + expect(mockHandleApiResult).toHaveBeenCalledWith( + errorResponse, + mockLogger, + 'Error removing task', + undefined, + validArgs.projectRoot + ); + }); + + test('should handle path finding errors', async () => { + // Setup path finding error + mockFindTasksPath.mockImplementationOnce(() => { + throw new Error('No tasks.json found'); + }); + + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + const result = await executeFunction(validArgs, mockContext); + + // Verify error logging + expect(mockLogger.error).toHaveBeenCalledWith( + 'Error finding tasks.json: No tasks.json found' + ); + + // Verify error response was returned + expect(mockCreateErrorResponse).toHaveBeenCalledWith( + 'Failed to find tasks.json: No tasks.json found' + ); + + // Verify removeTaskDirect was NOT called + expect(mockRemoveTaskDirect).not.toHaveBeenCalled(); + }); + + test('should handle unexpected errors in execute function', async () => { + // Setup unexpected error + mockRemoveTaskDirect.mockImplementationOnce(() => { + throw new Error('Unexpected error'); + }); + + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + await executeFunction(validArgs, mockContext); + + // Verify error logging + expect(mockLogger.error).toHaveBeenCalledWith( + 'Error in remove-task tool: Unexpected error' + ); + + // Verify error response was returned + expect(mockCreateErrorResponse).toHaveBeenCalledWith('Unexpected error'); + }); + + test('should properly handle withNormalizedProjectRoot wrapper', () => { + // Verify that withNormalizedProjectRoot was called with the execute function + expect(mockWithNormalizedProjectRoot).toHaveBeenCalledWith( + expect.any(Function) + ); + }); + + test('should log appropriate info messages for successful operations', async () => { + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + await executeFunction(validArgs, mockContext); + + // Verify appropriate logging + expect(mockLogger.info).toHaveBeenCalledWith( + 'Removing task(s) with ID(s): 5' + ); + expect(mockLogger.info).toHaveBeenCalledWith( + 'Using tasks file path: /mock/project/tasks.json' + ); + expect(mockLogger.info).toHaveBeenCalledWith( + 'Successfully removed task: 5' + ); + }); + + test('should handle subtask removal with proper tag context', async () => { + const subtaskArgs = { + id: '5.2', + projectRoot: '/mock/project/root', + tag: 'feature-branch' + }; + + const subtaskSuccessResponse = { + success: true, + data: { + totalTasks: 1, + successful: 1, + failed: 0, + removedTasks: [ + { + id: 2, + title: 'Removed Subtask', + status: 'pending', + parentTaskId: 5 + } + ], + messages: [ + "Successfully removed subtask 5.2 from tag 'feature-branch'" + ], + errors: [], + tasksPath: '/mock/project/tasks.json', + tag: 'feature-branch' + } + }; + + mockRemoveTaskDirect.mockResolvedValueOnce(subtaskSuccessResponse); + + // Setup context + const mockContext = { + log: mockLogger, + session: { workingDirectory: '/mock/dir' } + }; + + // Execute the function + await executeFunction(subtaskArgs, mockContext); + + // Verify removeTaskDirect was called with subtask ID and tag + expect(mockRemoveTaskDirect).toHaveBeenCalledWith( + expect.objectContaining({ + id: '5.2', + tag: 'feature-branch' + }), + mockLogger, + expect.any(Object) + ); + + // Verify successful handling + expect(mockHandleApiResult).toHaveBeenCalledWith( + subtaskSuccessResponse, + mockLogger, + 'Error removing task', + undefined, + subtaskArgs.projectRoot + ); + }); +}); diff --git a/tests/unit/scripts/modules/dependency-manager/fix-dependencies-command.test.js b/tests/unit/scripts/modules/dependency-manager/fix-dependencies-command.test.js new file mode 100644 index 00000000..264e0303 --- /dev/null +++ b/tests/unit/scripts/modules/dependency-manager/fix-dependencies-command.test.js @@ -0,0 +1,190 @@ +/** + * Unit test to ensure fixDependenciesCommand writes JSON with the correct + * projectRoot and tag arguments so that tag data is preserved. + */ + +import { jest } from '@jest/globals'; + +// Mock process.exit to prevent test termination +const mockProcessExit = jest.fn(); +const originalExit = process.exit; +process.exit = mockProcessExit; + +// Mock utils.js BEFORE importing the module under test +jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({ + readJSON: jest.fn(), + writeJSON: jest.fn(), + log: jest.fn(), + findProjectRoot: jest.fn(() => '/mock/project/root'), + getCurrentTag: jest.fn(() => 'master'), + taskExists: jest.fn(() => true), + formatTaskId: jest.fn((id) => id), + findCycles: jest.fn(() => []), + isSilentMode: jest.fn(() => true), + resolveTag: jest.fn(() => 'master'), + getTasksForTag: jest.fn(() => []), + setTasksForTag: jest.fn(), + enableSilentMode: jest.fn(), + disableSilentMode: jest.fn() +})); + +// Mock ui.js +jest.unstable_mockModule('../../../../../scripts/modules/ui.js', () => ({ + displayBanner: jest.fn() +})); + +// Mock task-manager.js +jest.unstable_mockModule( + '../../../../../scripts/modules/task-manager.js', + () => ({ + generateTaskFiles: jest.fn() + }) +); + +// Mock external libraries +jest.unstable_mockModule('chalk', () => ({ + default: { + green: jest.fn((text) => text), + cyan: jest.fn((text) => text), + bold: jest.fn((text) => text) + } +})); + +jest.unstable_mockModule('boxen', () => ({ + default: jest.fn((text) => text) +})); + +// Import the mocked modules +const { readJSON, writeJSON, log, taskExists } = await import( + '../../../../../scripts/modules/utils.js' +); + +// Import the module under test +const { fixDependenciesCommand } = await import( + '../../../../../scripts/modules/dependency-manager.js' +); + +describe('fixDependenciesCommand tag preservation', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockProcessExit.mockClear(); + }); + + afterAll(() => { + // Restore original process.exit + process.exit = originalExit; + }); + + it('calls writeJSON with projectRoot and tag parameters when changes are made', async () => { + const tasksPath = '/mock/tasks.json'; + const projectRoot = '/mock/project/root'; + const tag = 'master'; + + // Mock data WITH dependency issues to trigger writeJSON + const tasksDataWithIssues = { + tasks: [ + { + id: 1, + title: 'Task 1', + dependencies: [999] // Non-existent dependency to trigger fix + }, + { + id: 2, + title: 'Task 2', + dependencies: [] + } + ], + tag: 'master', + _rawTaggedData: { + master: { + tasks: [ + { + id: 1, + title: 'Task 1', + dependencies: [999] + } + ] + } + } + }; + + readJSON.mockReturnValue(tasksDataWithIssues); + taskExists.mockReturnValue(false); // Make dependency invalid to trigger fix + + await fixDependenciesCommand(tasksPath, { + context: { projectRoot, tag } + }); + + // Verify readJSON was called with correct parameters + expect(readJSON).toHaveBeenCalledWith(tasksPath, projectRoot, tag); + + // Verify writeJSON was called (should be triggered by removing invalid dependency) + expect(writeJSON).toHaveBeenCalled(); + + // Check the writeJSON call parameters + const writeJSONCalls = writeJSON.mock.calls; + const lastWriteCall = writeJSONCalls[writeJSONCalls.length - 1]; + const [calledPath, _data, calledProjectRoot, calledTag] = lastWriteCall; + + expect(calledPath).toBe(tasksPath); + expect(calledProjectRoot).toBe(projectRoot); + expect(calledTag).toBe(tag); + + // Verify process.exit was NOT called (meaning the function succeeded) + expect(mockProcessExit).not.toHaveBeenCalled(); + }); + + it('does not call writeJSON when no changes are needed', async () => { + const tasksPath = '/mock/tasks.json'; + const projectRoot = '/mock/project/root'; + const tag = 'master'; + + // Mock data WITHOUT dependency issues (no changes needed) + const cleanTasksData = { + tasks: [ + { + id: 1, + title: 'Task 1', + dependencies: [] // Clean, no issues + } + ], + tag: 'master' + }; + + readJSON.mockReturnValue(cleanTasksData); + taskExists.mockReturnValue(true); // All dependencies exist + + await fixDependenciesCommand(tasksPath, { + context: { projectRoot, tag } + }); + + // Verify readJSON was called + expect(readJSON).toHaveBeenCalledWith(tasksPath, projectRoot, tag); + + // Verify writeJSON was NOT called (no changes needed) + expect(writeJSON).not.toHaveBeenCalled(); + + // Verify process.exit was NOT called + expect(mockProcessExit).not.toHaveBeenCalled(); + }); + + it('handles early exit when no valid tasks found', async () => { + const tasksPath = '/mock/tasks.json'; + + // Mock invalid data to trigger early exit + readJSON.mockReturnValue(null); + + await fixDependenciesCommand(tasksPath, { + context: { projectRoot: '/mock', tag: 'master' } + }); + + // Verify readJSON was called + expect(readJSON).toHaveBeenCalled(); + + // Verify writeJSON was NOT called (early exit) + expect(writeJSON).not.toHaveBeenCalled(); + + // Verify process.exit WAS called due to invalid data + expect(mockProcessExit).toHaveBeenCalledWith(1); + }); +}); diff --git a/tests/unit/scripts/modules/task-manager/add-subtask.test.js b/tests/unit/scripts/modules/task-manager/add-subtask.test.js index 7980778a..eeaf6ef7 100644 --- a/tests/unit/scripts/modules/task-manager/add-subtask.test.js +++ b/tests/unit/scripts/modules/task-manager/add-subtask.test.js @@ -2,308 +2,171 @@ * Tests for the addSubtask function */ import { jest } from '@jest/globals'; -import path from 'path'; -// Mock dependencies -const mockReadJSON = jest.fn(); -const mockWriteJSON = jest.fn(); -const mockGenerateTaskFiles = jest.fn(); -const mockIsTaskDependentOn = jest.fn().mockReturnValue(false); - -// Mock path module -jest.mock('path', () => ({ - dirname: jest.fn() -})); - -// Define test version of the addSubtask function -const testAddSubtask = ( - tasksPath, - parentId, - existingTaskId, - newSubtaskData, - generateFiles = true -) => { - // Read the existing tasks - const data = mockReadJSON(tasksPath); - if (!data || !data.tasks) { - throw new Error(`Invalid or missing tasks file at ${tasksPath}`); - } - - // Convert parent ID to number - const parentIdNum = parseInt(parentId, 10); - - // Find the parent task - const parentTask = data.tasks.find((t) => t.id === parentIdNum); - if (!parentTask) { - throw new Error(`Parent task with ID ${parentIdNum} not found`); - } - - // Initialize subtasks array if it doesn't exist - if (!parentTask.subtasks) { - parentTask.subtasks = []; - } - - let newSubtask; - - // Case 1: Convert an existing task to a subtask - if (existingTaskId !== null) { - const existingTaskIdNum = parseInt(existingTaskId, 10); - - // Find the existing task - const existingTaskIndex = data.tasks.findIndex( - (t) => t.id === existingTaskIdNum - ); - if (existingTaskIndex === -1) { - throw new Error(`Task with ID ${existingTaskIdNum} not found`); - } - - const existingTask = data.tasks[existingTaskIndex]; - - // Check if task is already a subtask - if (existingTask.parentTaskId) { - throw new Error( - `Task ${existingTaskIdNum} is already a subtask of task ${existingTask.parentTaskId}` - ); - } - - // Check for circular dependency - if (existingTaskIdNum === parentIdNum) { - throw new Error(`Cannot make a task a subtask of itself`); - } - - // Check for circular dependency using mockIsTaskDependentOn - if (mockIsTaskDependentOn()) { - throw new Error( - `Cannot create circular dependency: task ${parentIdNum} is already a subtask or dependent of task ${existingTaskIdNum}` - ); - } - - // Find the highest subtask ID to determine the next ID - const highestSubtaskId = - parentTask.subtasks.length > 0 - ? Math.max(...parentTask.subtasks.map((st) => st.id)) - : 0; - const newSubtaskId = highestSubtaskId + 1; - - // Clone the existing task to be converted to a subtask - newSubtask = { - ...existingTask, - id: newSubtaskId, - parentTaskId: parentIdNum - }; - - // Add to parent's subtasks - parentTask.subtasks.push(newSubtask); - - // Remove the task from the main tasks array - data.tasks.splice(existingTaskIndex, 1); - } - // Case 2: Create a new subtask - else if (newSubtaskData) { - // Find the highest subtask ID to determine the next ID - const highestSubtaskId = - parentTask.subtasks.length > 0 - ? Math.max(...parentTask.subtasks.map((st) => st.id)) - : 0; - const newSubtaskId = highestSubtaskId + 1; - - // Create the new subtask object - newSubtask = { - id: newSubtaskId, - title: newSubtaskData.title, - description: newSubtaskData.description || '', - details: newSubtaskData.details || '', - status: newSubtaskData.status || 'pending', - dependencies: newSubtaskData.dependencies || [], - parentTaskId: parentIdNum - }; - - // Add to parent's subtasks - parentTask.subtasks.push(newSubtask); - } else { - throw new Error('Either existingTaskId or newSubtaskData must be provided'); - } - - // Write the updated tasks back to the file - mockWriteJSON(tasksPath, data); - - // Generate task files if requested - if (generateFiles) { - mockGenerateTaskFiles(tasksPath, path.dirname(tasksPath)); - } - - return newSubtask; +// Mock dependencies before importing the module +const mockUtils = { + readJSON: jest.fn(), + writeJSON: jest.fn(), + log: jest.fn(), + getCurrentTag: jest.fn() }; +const mockTaskManager = { + isTaskDependentOn: jest.fn() +}; +const mockGenerateTaskFiles = jest.fn(); + +jest.unstable_mockModule( + '../../../../../scripts/modules/utils.js', + () => mockUtils +); +jest.unstable_mockModule( + '../../../../../scripts/modules/task-manager.js', + () => mockTaskManager +); +jest.unstable_mockModule( + '../../../../../scripts/modules/task-manager/generate-task-files.js', + () => ({ + default: mockGenerateTaskFiles + }) +); + +const addSubtask = ( + await import('../../../../../scripts/modules/task-manager/add-subtask.js') +).default; describe('addSubtask function', () => { - // Reset mocks before each test + const multiTagData = { + master: { + tasks: [{ id: 1, title: 'Master Task', subtasks: [] }], + metadata: { description: 'Master tasks' } + }, + 'feature-branch': { + tasks: [{ id: 1, title: 'Feature Task', subtasks: [] }], + metadata: { description: 'Feature tasks' } + } + }; + beforeEach(() => { jest.clearAllMocks(); + mockTaskManager.isTaskDependentOn.mockReturnValue(false); + }); - // Default mock implementations - mockReadJSON.mockImplementation(() => ({ - tasks: [ - { - id: 1, - title: 'Parent Task', - description: 'This is a parent task', - status: 'pending', - dependencies: [] - }, - { - id: 2, - title: 'Existing Task', - description: 'This is an existing task', - status: 'pending', - dependencies: [] - }, - { - id: 3, - title: 'Another Task', - description: 'This is another task', - status: 'pending', - dependencies: [1] - } - ] - })); - - // Setup success write response - mockWriteJSON.mockImplementation((path, data) => { - return data; + test('should add a new subtask and preserve other tags', async () => { + const context = { projectRoot: '/fake/root', tag: 'feature-branch' }; + const newSubtaskData = { title: 'My New Subtask' }; + mockUtils.readJSON.mockReturnValueOnce({ + tasks: [{ id: 1, title: 'Feature Task', subtasks: [] }], + metadata: { description: 'Feature tasks' } }); - // Set up default behavior for dependency check - mockIsTaskDependentOn.mockReturnValue(false); + await addSubtask('tasks.json', '1', null, newSubtaskData, true, context); + + expect(mockUtils.writeJSON).toHaveBeenCalledWith( + 'tasks.json', + expect.any(Object), + '/fake/root', + 'feature-branch' + ); + const writtenData = mockUtils.writeJSON.mock.calls[0][1]; + const parentTask = writtenData.tasks.find((t) => t.id === 1); + expect(parentTask.subtasks).toHaveLength(1); + expect(parentTask.subtasks[0].title).toBe('My New Subtask'); }); test('should add a new subtask to a parent task', async () => { - // Create new subtask data - const newSubtaskData = { - title: 'New Subtask', - description: 'This is a new subtask', - details: 'Implementation details for the subtask', - status: 'pending', - dependencies: [] - }; - - // Execute the test version of addSubtask - const newSubtask = testAddSubtask( - 'tasks/tasks.json', - 1, + mockUtils.readJSON.mockReturnValueOnce({ + tasks: [{ id: 1, title: 'Parent Task', subtasks: [] }] + }); + const context = {}; + const newSubtask = await addSubtask( + 'tasks.json', + '1', null, - newSubtaskData, - true + { title: 'New Subtask' }, + true, + context ); - - // Verify readJSON was called with the correct path - expect(mockReadJSON).toHaveBeenCalledWith('tasks/tasks.json'); - - // Verify writeJSON was called with the correct path - expect(mockWriteJSON).toHaveBeenCalledWith( - 'tasks/tasks.json', - expect.any(Object) - ); - - // Verify the subtask was created with correct data expect(newSubtask).toBeDefined(); expect(newSubtask.id).toBe(1); - expect(newSubtask.title).toBe('New Subtask'); expect(newSubtask.parentTaskId).toBe(1); - - // Verify generateTaskFiles was called + expect(mockUtils.writeJSON).toHaveBeenCalled(); + const writeCallArgs = mockUtils.writeJSON.mock.calls[0][1]; // data is the second arg now + const parentTask = writeCallArgs.tasks.find((t) => t.id === 1); + expect(parentTask.subtasks).toHaveLength(1); + expect(parentTask.subtasks[0].title).toBe('New Subtask'); expect(mockGenerateTaskFiles).toHaveBeenCalled(); }); test('should convert an existing task to a subtask', async () => { - // Execute the test version of addSubtask to convert task 2 to a subtask of task 1 - const convertedSubtask = testAddSubtask( - 'tasks/tasks.json', - 1, - 2, + mockUtils.readJSON.mockReturnValueOnce({ + tasks: [ + { id: 1, title: 'Parent Task', subtasks: [] }, + { id: 2, title: 'Existing Task 2', subtasks: [] } + ] + }); + const context = {}; + const convertedSubtask = await addSubtask( + 'tasks.json', + '1', + '2', null, - true + true, + context ); - - // Verify readJSON was called with the correct path - expect(mockReadJSON).toHaveBeenCalledWith('tasks/tasks.json'); - - // Verify writeJSON was called - expect(mockWriteJSON).toHaveBeenCalled(); - - // Verify the subtask was created with correct data - expect(convertedSubtask).toBeDefined(); expect(convertedSubtask.id).toBe(1); - expect(convertedSubtask.title).toBe('Existing Task'); expect(convertedSubtask.parentTaskId).toBe(1); - - // Verify generateTaskFiles was called - expect(mockGenerateTaskFiles).toHaveBeenCalled(); + expect(convertedSubtask.title).toBe('Existing Task 2'); + expect(mockUtils.writeJSON).toHaveBeenCalled(); + const writeCallArgs = mockUtils.writeJSON.mock.calls[0][1]; + const parentTask = writeCallArgs.tasks.find((t) => t.id === 1); + expect(parentTask.subtasks).toHaveLength(1); + expect(parentTask.subtasks[0].title).toBe('Existing Task 2'); }); test('should throw an error if parent task does not exist', async () => { - // Create new subtask data - const newSubtaskData = { - title: 'New Subtask', - description: 'This is a new subtask' - }; + mockUtils.readJSON.mockReturnValueOnce({ + tasks: [{ id: 1, title: 'Task 1', subtasks: [] }] + }); + const context = {}; + await expect( + addSubtask( + 'tasks.json', + '99', + null, + { title: 'New Subtask' }, + true, + context + ) + ).rejects.toThrow('Parent task with ID 99 not found'); + }); - // Override mockReadJSON for this specific test case - mockReadJSON.mockImplementationOnce(() => ({ + test('should throw an error if trying to convert a non-existent task', async () => { + mockUtils.readJSON.mockReturnValueOnce({ + tasks: [{ id: 1, title: 'Parent Task', subtasks: [] }] + }); + const context = {}; + await expect( + addSubtask('tasks.json', '1', '99', null, true, context) + ).rejects.toThrow('Task with ID 99 not found'); + }); + + test('should throw an error for circular dependency', async () => { + mockUtils.readJSON.mockReturnValueOnce({ tasks: [ - { - id: 1, - title: 'Task 1', - status: 'pending' - } + { id: 1, title: 'Parent Task', subtasks: [] }, + { id: 2, title: 'Child Task', subtasks: [] } ] - })); - - // Expect an error when trying to add a subtask to a non-existent parent - expect(() => - testAddSubtask('tasks/tasks.json', 999, null, newSubtaskData) - ).toThrow(/Parent task with ID 999 not found/); - - // Verify writeJSON was not called - expect(mockWriteJSON).not.toHaveBeenCalled(); - }); - - test('should throw an error if existing task does not exist', async () => { - // Expect an error when trying to convert a non-existent task - expect(() => testAddSubtask('tasks/tasks.json', 1, 999, null)).toThrow( - /Task with ID 999 not found/ + }); + mockTaskManager.isTaskDependentOn.mockImplementation( + (tasks, parentTask, existingTaskIdNum) => { + return parentTask.id === 1 && existingTaskIdNum === 2; + } ); - - // Verify writeJSON was not called - expect(mockWriteJSON).not.toHaveBeenCalled(); - }); - - test('should throw an error if trying to create a circular dependency', async () => { - // Force the isTaskDependentOn mock to return true for this test only - mockIsTaskDependentOn.mockReturnValueOnce(true); - - // Expect an error when trying to create a circular dependency - expect(() => testAddSubtask('tasks/tasks.json', 3, 1, null)).toThrow( - /circular dependency/ + const context = {}; + await expect( + addSubtask('tasks.json', '1', '2', null, true, context) + ).rejects.toThrow( + 'Cannot create circular dependency: task 1 is already a subtask or dependent of task 2' ); - - // Verify writeJSON was not called - expect(mockWriteJSON).not.toHaveBeenCalled(); - }); - - test('should not regenerate task files if generateFiles is false', async () => { - // Create new subtask data - const newSubtaskData = { - title: 'New Subtask', - description: 'This is a new subtask' - }; - - // Execute the test version of addSubtask with generateFiles = false - testAddSubtask('tasks/tasks.json', 1, null, newSubtaskData, false); - - // Verify writeJSON was called - expect(mockWriteJSON).toHaveBeenCalled(); - - // Verify task files were not regenerated - expect(mockGenerateTaskFiles).not.toHaveBeenCalled(); }); }); diff --git a/tests/unit/scripts/modules/task-manager/add-task.test.js b/tests/unit/scripts/modules/task-manager/add-task.test.js index 4f894729..2aae8777 100644 --- a/tests/unit/scripts/modules/task-manager/add-task.test.js +++ b/tests/unit/scripts/modules/task-manager/add-task.test.js @@ -258,7 +258,9 @@ describe('addTask', () => { }) ]) }) - }) + }), + '/mock/project/root', // projectRoot parameter + 'master' // tag parameter ); expect(result).toEqual( expect.objectContaining({ @@ -299,7 +301,9 @@ describe('addTask', () => { }) ]) }) - }) + }), + '/mock/project/root', // projectRoot parameter + 'master' // tag parameter ); }); @@ -334,7 +338,9 @@ describe('addTask', () => { }) ]) }) - }) + }), + '/mock/project/root', // projectRoot parameter + 'master' // tag parameter ); expect(context.mcpLog.warn).toHaveBeenCalledWith( expect.stringContaining( @@ -366,7 +372,9 @@ describe('addTask', () => { }) ]) }) - }) + }), + '/mock/project/root', // projectRoot parameter + 'master' // tag parameter ); }); @@ -401,7 +409,9 @@ describe('addTask', () => { }) ]) }) - }) + }), + '/mock/project/root', // projectRoot parameter + 'master' // tag parameter ); }); diff --git a/tests/unit/scripts/modules/task-manager/analyze-task-complexity.test.js b/tests/unit/scripts/modules/task-manager/analyze-task-complexity.test.js index 09d86477..3e6c13a6 100644 --- a/tests/unit/scripts/modules/task-manager/analyze-task-complexity.test.js +++ b/tests/unit/scripts/modules/task-manager/analyze-task-complexity.test.js @@ -2,6 +2,10 @@ * Tests for the analyze-task-complexity.js module */ import { jest } from '@jest/globals'; +import { + createGetTagAwareFilePathMock, + createSlugifyTagForFilePathMock +} from './setup.js'; // Mock the dependencies before importing the module under test jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({ @@ -32,6 +36,8 @@ jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({ ensureTagMetadata: jest.fn((tagObj) => tagObj), getCurrentTag: jest.fn(() => 'master'), flattenTasksWithSubtasks: jest.fn((tasks) => tasks), + getTagAwareFilePath: createGetTagAwareFilePathMock(), + slugifyTagForFilePath: createSlugifyTagForFilePathMock(), markMigrationForNotice: jest.fn(), performCompleteTagMigration: jest.fn(), setTasksForTag: jest.fn(), diff --git a/tests/unit/scripts/modules/task-manager/expand-task.test.js b/tests/unit/scripts/modules/task-manager/expand-task.test.js index 07c68fed..5a3b5cd6 100644 --- a/tests/unit/scripts/modules/task-manager/expand-task.test.js +++ b/tests/unit/scripts/modules/task-manager/expand-task.test.js @@ -3,6 +3,10 @@ */ import { jest } from '@jest/globals'; import fs from 'fs'; +import { + createGetTagAwareFilePathMock, + createSlugifyTagForFilePathMock +} from './setup.js'; // Mock the dependencies before importing the module under test jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({ @@ -36,6 +40,8 @@ jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({ } return allTasks; }), + getTagAwareFilePath: createGetTagAwareFilePathMock(), + slugifyTagForFilePath: createSlugifyTagForFilePathMock(), readComplexityReport: jest.fn(), markMigrationForNotice: jest.fn(), performCompleteTagMigration: jest.fn(), @@ -116,7 +122,8 @@ jest.unstable_mockModule( '../../../../../scripts/modules/config-manager.js', () => ({ getDefaultSubtasks: jest.fn(() => 3), - getDebugFlag: jest.fn(() => false) + getDebugFlag: jest.fn(() => false), + getDefaultNumTasks: jest.fn(() => 10) }) ); @@ -193,6 +200,10 @@ const generateTaskFiles = ( ) ).default; +const { getDefaultSubtasks } = await import( + '../../../../../scripts/modules/config-manager.js' +); + // Import the module under test const { default: expandTask } = await import( '../../../../../scripts/modules/task-manager/expand-task.js' @@ -649,6 +660,61 @@ describe('expandTask', () => { }); }); + describe('Complexity Report Integration (Tag-Specific)', () => { + test('should use tag-specific complexity report when available', async () => { + // Arrange + const tasksPath = 'tasks/tasks.json'; + const taskId = '1'; // Task in feature-branch + const context = { + mcpLog: createMcpLogMock(), + projectRoot: '/mock/project/root', + tag: 'feature-branch' + }; + + // Stub fs.existsSync to simulate complexity report exists for this tag + const existsSpy = jest + .spyOn(fs, 'existsSync') + .mockImplementation((filepath) => + filepath.endsWith('task-complexity-report_feature-branch.json') + ); + + // Stub readJSON to return complexity report when reading the report path + readJSON.mockImplementation((filepath, projectRootParam, tagParam) => { + if (filepath.includes('task-complexity-report_feature-branch.json')) { + return { + complexityAnalysis: [ + { + taskId: 1, + complexityScore: 8, + recommendedSubtasks: 5, + reasoning: 'Needs five detailed steps', + expansionPrompt: 'Please break this task into 5 parts' + } + ] + }; + } + // Default tasks data for tasks.json + const sampleTasksCopy = JSON.parse(JSON.stringify(sampleTasks)); + const selectedTag = tagParam || 'master'; + return { + ...sampleTasksCopy[selectedTag], + tag: selectedTag, + _rawTaggedData: sampleTasksCopy + }; + }); + + // Act + await expandTask(tasksPath, taskId, undefined, false, '', context, false); + + // Assert - generateTextService called with systemPrompt for 5 subtasks + const callArg = generateTextService.mock.calls[0][0]; + expect(callArg.systemPrompt).toContain('Generate exactly 5 subtasks'); + + // Clean up stub + existsSpy.mockRestore(); + }); + }); + describe('Error Handling', () => { test('should handle non-existent task ID', async () => { // Arrange @@ -885,4 +951,120 @@ describe('expandTask', () => { ); }); }); + + describe('Dynamic Subtask Generation', () => { + const tasksPath = 'tasks/tasks.json'; + const taskId = 1; + const context = { session: null, mcpLog: null }; + + beforeEach(() => { + // Reset all mocks + jest.clearAllMocks(); + + // Setup default mocks + readJSON.mockReturnValue({ + tasks: [ + { + id: 1, + title: 'Test Task', + description: 'A test task', + status: 'pending', + subtasks: [] + } + ] + }); + + findTaskById.mockReturnValue({ + id: 1, + title: 'Test Task', + description: 'A test task', + status: 'pending', + subtasks: [] + }); + + findProjectRoot.mockReturnValue('/mock/project/root'); + }); + + test('should accept 0 as valid numSubtasks value for dynamic generation', async () => { + // Act - Call with numSubtasks=0 (should not throw error) + const result = await expandTask( + tasksPath, + taskId, + 0, + false, + '', + context, + false + ); + + // Assert - Should complete successfully + expect(result).toBeDefined(); + expect(generateTextService).toHaveBeenCalled(); + }); + + test('should use dynamic prompting when numSubtasks is 0', async () => { + // Act + await expandTask(tasksPath, taskId, 0, false, '', context, false); + + // Assert - Verify generateTextService was called + expect(generateTextService).toHaveBeenCalled(); + + // Get the call arguments to verify the system prompt + const callArgs = generateTextService.mock.calls[0][0]; + expect(callArgs.systemPrompt).toContain( + 'an appropriate number of specific subtasks' + ); + }); + + test('should use specific count prompting when numSubtasks is positive', async () => { + // Act + await expandTask(tasksPath, taskId, 5, false, '', context, false); + + // Assert - Verify generateTextService was called + expect(generateTextService).toHaveBeenCalled(); + + // Get the call arguments to verify the system prompt + const callArgs = generateTextService.mock.calls[0][0]; + expect(callArgs.systemPrompt).toContain('5 specific subtasks'); + }); + + test('should reject negative numSubtasks values and fallback to default', async () => { + // Mock getDefaultSubtasks to return a specific value + getDefaultSubtasks.mockReturnValue(4); + + // Act + await expandTask(tasksPath, taskId, -3, false, '', context, false); + + // Assert - Should use default value instead of negative + expect(generateTextService).toHaveBeenCalled(); + const callArgs = generateTextService.mock.calls[0][0]; + expect(callArgs.systemPrompt).toContain('4 specific subtasks'); + }); + + test('should use getDefaultSubtasks when numSubtasks is undefined', async () => { + // Mock getDefaultSubtasks to return a specific value + getDefaultSubtasks.mockReturnValue(6); + + // Act - Call without specifying numSubtasks (undefined) + await expandTask(tasksPath, taskId, undefined, false, '', context, false); + + // Assert - Should use default value + expect(generateTextService).toHaveBeenCalled(); + const callArgs = generateTextService.mock.calls[0][0]; + expect(callArgs.systemPrompt).toContain('6 specific subtasks'); + }); + + test('should use getDefaultSubtasks when numSubtasks is null', async () => { + // Mock getDefaultSubtasks to return a specific value + getDefaultSubtasks.mockReturnValue(7); + + // Act - Call with null numSubtasks + await expandTask(tasksPath, taskId, null, false, '', context, false); + + // Assert - Should use default value + expect(generateTextService).toHaveBeenCalled(); + const callArgs = generateTextService.mock.calls[0][0]; + expect(callArgs.systemPrompt).toContain('7 specific subtasks'); + }); + }); }); diff --git a/tests/unit/scripts/modules/task-manager/parse-prd.test.js b/tests/unit/scripts/modules/task-manager/parse-prd.test.js index ff87b8c1..e5ff755a 100644 --- a/tests/unit/scripts/modules/task-manager/parse-prd.test.js +++ b/tests/unit/scripts/modules/task-manager/parse-prd.test.js @@ -47,7 +47,8 @@ jest.unstable_mockModule('../../../../../scripts/modules/ui.js', () => ({ jest.unstable_mockModule( '../../../../../scripts/modules/config-manager.js', () => ({ - getDebugFlag: jest.fn(() => false) + getDebugFlag: jest.fn(() => false), + getDefaultNumTasks: jest.fn(() => 10) }) ); @@ -94,13 +95,15 @@ jest.unstable_mockModule('path', () => ({ })); // Import the mocked modules -const { readJSON, writeJSON, log, promptYesNo } = await import( +const { readJSON, promptYesNo } = await import( '../../../../../scripts/modules/utils.js' ); const { generateObjectService } = await import( '../../../../../scripts/modules/ai-services-unified.js' ); + +// Note: getDefaultNumTasks validation happens at CLI/MCP level, not in the main parse-prd module const generateTaskFiles = ( await import( '../../../../../scripts/modules/task-manager/generate-task-files.js' @@ -433,4 +436,123 @@ describe('parsePRD', () => { // Verify prompt was NOT called with append flag expect(promptYesNo).not.toHaveBeenCalled(); }); + + describe('Dynamic Task Generation', () => { + test('should use dynamic prompting when numTasks is 0', async () => { + // Setup mocks to simulate normal conditions (no existing output file) + fs.default.existsSync.mockImplementation((p) => { + if (p === 'tasks/tasks.json') return false; // Output file doesn't exist + if (p === 'tasks') return true; // Directory exists + return false; + }); + + // Call the function with numTasks=0 for dynamic generation + await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 0); + + // Verify generateObjectService was called + expect(generateObjectService).toHaveBeenCalled(); + + // Get the call arguments to verify the prompt + const callArgs = generateObjectService.mock.calls[0][0]; + expect(callArgs.prompt).toContain('an appropriate number of'); + expect(callArgs.prompt).not.toContain('approximately 0'); + }); + + test('should use specific count prompting when numTasks is positive', async () => { + // Setup mocks to simulate normal conditions (no existing output file) + fs.default.existsSync.mockImplementation((p) => { + if (p === 'tasks/tasks.json') return false; // Output file doesn't exist + if (p === 'tasks') return true; // Directory exists + return false; + }); + + // Call the function with specific numTasks + await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 5); + + // Verify generateObjectService was called + expect(generateObjectService).toHaveBeenCalled(); + + // Get the call arguments to verify the prompt + const callArgs = generateObjectService.mock.calls[0][0]; + expect(callArgs.prompt).toContain('approximately 5'); + expect(callArgs.prompt).not.toContain('an appropriate number of'); + }); + + test('should accept 0 as valid numTasks value', async () => { + // Setup mocks to simulate normal conditions (no existing output file) + fs.default.existsSync.mockImplementation((p) => { + if (p === 'tasks/tasks.json') return false; // Output file doesn't exist + if (p === 'tasks') return true; // Directory exists + return false; + }); + + // Call the function with numTasks=0 - should not throw error + const result = await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 0); + + // Verify it completed successfully + expect(result).toEqual({ + success: true, + tasksPath: 'tasks/tasks.json', + telemetryData: {} + }); + }); + + test('should use dynamic prompting when numTasks is negative (no validation in main module)', async () => { + // Setup mocks to simulate normal conditions (no existing output file) + fs.default.existsSync.mockImplementation((p) => { + if (p === 'tasks/tasks.json') return false; // Output file doesn't exist + if (p === 'tasks') return true; // Directory exists + return false; + }); + + // Call the function with negative numTasks + // Note: The main parse-prd.js module doesn't validate numTasks - validation happens at CLI/MCP level + await parsePRD('path/to/prd.txt', 'tasks/tasks.json', -5); + + // Verify generateObjectService was called + expect(generateObjectService).toHaveBeenCalled(); + const callArgs = generateObjectService.mock.calls[0][0]; + // Negative values are treated as <= 0, so should use dynamic prompting + expect(callArgs.prompt).toContain('an appropriate number of'); + expect(callArgs.prompt).not.toContain('approximately -5'); + }); + }); + + describe('Configuration Integration', () => { + test('should use dynamic prompting when numTasks is null', async () => { + // Setup mocks to simulate normal conditions (no existing output file) + fs.default.existsSync.mockImplementation((p) => { + if (p === 'tasks/tasks.json') return false; // Output file doesn't exist + if (p === 'tasks') return true; // Directory exists + return false; + }); + + // Call the function with null numTasks + await parsePRD('path/to/prd.txt', 'tasks/tasks.json', null); + + // Verify generateObjectService was called with dynamic prompting + expect(generateObjectService).toHaveBeenCalled(); + const callArgs = generateObjectService.mock.calls[0][0]; + expect(callArgs.prompt).toContain('an appropriate number of'); + }); + + test('should use dynamic prompting when numTasks is invalid string', async () => { + // Setup mocks to simulate normal conditions (no existing output file) + fs.default.existsSync.mockImplementation((p) => { + if (p === 'tasks/tasks.json') return false; // Output file doesn't exist + if (p === 'tasks') return true; // Directory exists + return false; + }); + + // Call the function with invalid numTasks (string that's not a number) + await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 'invalid'); + + // Verify generateObjectService was called with dynamic prompting + // Note: The main module doesn't validate - it just uses the value as-is + // Since 'invalid' > 0 is false, it uses dynamic prompting + expect(generateObjectService).toHaveBeenCalled(); + const callArgs = generateObjectService.mock.calls[0][0]; + expect(callArgs.prompt).toContain('an appropriate number of'); + }); + }); }); diff --git a/tests/unit/scripts/modules/task-manager/set-task-status.test.js b/tests/unit/scripts/modules/task-manager/set-task-status.test.js index 6cbb8752..6e252b00 100644 --- a/tests/unit/scripts/modules/task-manager/set-task-status.test.js +++ b/tests/unit/scripts/modules/task-manager/set-task-status.test.js @@ -247,7 +247,9 @@ describe('setTaskStatus', () => { expect.objectContaining({ id: 2, status: 'done' }) ]) }) - }) + }), + undefined, + 'master' ); // expect(generateTaskFiles).toHaveBeenCalledWith( // tasksPath, @@ -287,7 +289,9 @@ describe('setTaskStatus', () => { }) ]) }) - }) + }), + undefined, + 'master' ); }); @@ -318,7 +322,9 @@ describe('setTaskStatus', () => { expect.objectContaining({ id: 2, status: 'done' }) ]) }) - }) + }), + undefined, + 'master' ); }); @@ -354,7 +360,9 @@ describe('setTaskStatus', () => { }) ]) }) - }) + }), + undefined, + 'master' ); }); @@ -524,4 +532,45 @@ describe('setTaskStatus', () => { ); expect(result).toBeDefined(); }); + + // Regression test to ensure tag preservation when updating in multi-tag environment + test('should preserve other tags when updating task status', async () => { + // Arrange + const multiTagData = { + master: JSON.parse(JSON.stringify(sampleTasks.master)), + 'feature-branch': { + tasks: [ + { id: 10, title: 'FB Task', status: 'pending', dependencies: [] } + ], + metadata: { description: 'Feature branch tasks' } + } + }; + const tasksPath = '/mock/path/tasks.json'; + + readJSON.mockReturnValue({ + ...multiTagData.master, // resolved view not used + tag: 'master', + _rawTaggedData: multiTagData + }); + + // Act + await setTaskStatus(tasksPath, '1', 'done', { + mcpLog: { info: jest.fn() } + }); + + // Assert: writeJSON should be called with data containing both tags intact + const writeArgs = writeJSON.mock.calls[0]; + expect(writeArgs[0]).toBe(tasksPath); + const writtenData = writeArgs[1]; + expect(writtenData).toHaveProperty('master'); + expect(writtenData).toHaveProperty('feature-branch'); + // master task updated + const updatedTask = writtenData.master.tasks.find((t) => t.id === 1); + expect(updatedTask.status).toBe('done'); + // feature-branch untouched + expect(writtenData['feature-branch'].tasks[0].status).toBe('pending'); + // ensure additional args (projectRoot undefined, tag 'master') present + expect(writeArgs[2]).toBeUndefined(); + expect(writeArgs[3]).toBe('master'); + }); }); diff --git a/tests/unit/scripts/modules/task-manager/setup.js b/tests/unit/scripts/modules/task-manager/setup.js index 55ff6bbb..a13ee6ba 100644 --- a/tests/unit/scripts/modules/task-manager/setup.js +++ b/tests/unit/scripts/modules/task-manager/setup.js @@ -119,3 +119,45 @@ export const setupCommonMocks = () => { // Helper to create a deep copy of objects to avoid test pollution export const cloneData = (data) => JSON.parse(JSON.stringify(data)); + +/** + * Shared mock implementation for getTagAwareFilePath that matches the actual implementation + * This ensures consistent behavior across all test files, particularly regarding projectRoot handling. + * + * The key difference from previous inconsistent implementations was that some tests were not + * properly handling the projectRoot parameter, leading to different behaviors between test files. + * + * @param {string} basePath - The base file path + * @param {string|null} tag - The tag name (null, undefined, or 'master' uses base path) + * @param {string} [projectRoot='.'] - The project root directory + * @returns {string} The resolved file path + */ +export const createGetTagAwareFilePathMock = () => { + return jest.fn((basePath, tag, projectRoot = '.') => { + // Handle projectRoot consistently - this was the key fix + const fullPath = projectRoot ? `${projectRoot}/${basePath}` : basePath; + + if (!tag || tag === 'master') { + return fullPath; + } + + // Mock the slugification behavior (matches actual implementation) + const slugifiedTag = tag.replace(/[^a-zA-Z0-9_-]/g, '-').toLowerCase(); + const idx = fullPath.lastIndexOf('.'); + return `${fullPath.slice(0, idx)}_${slugifiedTag}${fullPath.slice(idx)}`; + }); +}; + +/** + * Shared mock implementation for slugifyTagForFilePath that matches the actual implementation + * @param {string} tagName - The tag name to slugify + * @returns {string} Slugified tag name safe for filesystem use + */ +export const createSlugifyTagForFilePathMock = () => { + return jest.fn((tagName) => { + if (!tagName || typeof tagName !== 'string') { + return 'unknown-tag'; + } + return tagName.replace(/[^a-zA-Z0-9_-]/g, '-').toLowerCase(); + }); +}; diff --git a/tests/unit/scripts/modules/task-manager/update-tasks.test.js b/tests/unit/scripts/modules/task-manager/update-tasks.test.js index 3449b239..5dd51cae 100644 --- a/tests/unit/scripts/modules/task-manager/update-tasks.test.js +++ b/tests/unit/scripts/modules/task-manager/update-tasks.test.js @@ -165,7 +165,11 @@ describe('updateTasks', () => { // Assert // 1. Read JSON called - expect(readJSON).toHaveBeenCalledWith(mockTasksPath, '/mock/path'); + expect(readJSON).toHaveBeenCalledWith( + mockTasksPath, + '/mock/path', + 'master' + ); // 2. AI Service called with correct args expect(generateTextService).toHaveBeenCalledWith(expect.any(Object)); @@ -183,7 +187,9 @@ describe('updateTasks', () => { ]) }) }) - }) + }), + '/mock/path', + 'master' ); // 4. Check return value @@ -228,7 +234,11 @@ describe('updateTasks', () => { ); // Assert - expect(readJSON).toHaveBeenCalledWith(mockTasksPath, '/mock/path'); + expect(readJSON).toHaveBeenCalledWith( + mockTasksPath, + '/mock/path', + 'master' + ); expect(generateTextService).not.toHaveBeenCalled(); expect(writeJSON).not.toHaveBeenCalled(); expect(log).toHaveBeenCalledWith( @@ -239,4 +249,113 @@ describe('updateTasks', () => { // Should return early with no updates expect(result).toBeUndefined(); }); + + test('should preserve all tags when updating tasks in tagged context', async () => { + // Arrange - Simple 2-tag structure to test tag corruption fix + const mockTasksPath = '/mock/path/tasks.json'; + const mockFromId = 1; + const mockPrompt = 'Update master tag tasks'; + + const mockTaggedData = { + master: { + tasks: [ + { + id: 1, + title: 'Master Task', + status: 'pending', + details: 'Old details' + }, + { + id: 2, + title: 'Master Task 2', + status: 'done', + details: 'Done task' + } + ], + metadata: { + created: '2024-01-01T00:00:00.000Z', + description: 'Master tag tasks' + } + }, + 'feature-branch': { + tasks: [ + { + id: 1, + title: 'Feature Task', + status: 'pending', + details: 'Feature work' + } + ], + metadata: { + created: '2024-01-02T00:00:00.000Z', + description: 'Feature branch tasks' + } + } + }; + + const mockUpdatedTasks = [ + { + id: 1, + title: 'Updated Master Task', + status: 'pending', + details: 'Updated details', + description: 'Updated description', + dependencies: [], + priority: 'medium', + testStrategy: 'Test the updated functionality', + subtasks: [] + } + ]; + + // Configure mocks - readJSON returns resolved view for master tag + readJSON.mockReturnValue({ + ...mockTaggedData.master, + tag: 'master', + _rawTaggedData: mockTaggedData + }); + + generateTextService.mockResolvedValue({ + mainResult: JSON.stringify(mockUpdatedTasks), + telemetryData: { commandName: 'update-tasks', totalCost: 0.05 } + }); + + // Act + const result = await updateTasks( + mockTasksPath, + mockFromId, + mockPrompt, + false, // research + { projectRoot: '/mock/project/root', tag: 'master' }, + 'json' + ); + + // Assert - CRITICAL: Both tags must be preserved (this would fail before the fix) + expect(writeJSON).toHaveBeenCalledWith( + mockTasksPath, + expect.objectContaining({ + _rawTaggedData: expect.objectContaining({ + master: expect.objectContaining({ + tasks: expect.arrayContaining([ + expect.objectContaining({ id: 1, title: 'Updated Master Task' }), + expect.objectContaining({ id: 2, title: 'Master Task 2' }) // Unchanged done task + ]) + }), + // CRITICAL: This tag would be missing/corrupted if the bug existed + 'feature-branch': expect.objectContaining({ + tasks: expect.arrayContaining([ + expect.objectContaining({ id: 1, title: 'Feature Task' }) + ]), + metadata: expect.objectContaining({ + description: 'Feature branch tasks' + }) + }) + }) + }), + '/mock/project/root', + 'master' + ); + + expect(result.success).toBe(true); + expect(result.updatedTasks).toEqual(mockUpdatedTasks); + }); }); diff --git a/tests/unit/scripts/modules/utils-tag-aware-paths.test.js b/tests/unit/scripts/modules/utils-tag-aware-paths.test.js new file mode 100644 index 00000000..1fa9ad6b --- /dev/null +++ b/tests/unit/scripts/modules/utils-tag-aware-paths.test.js @@ -0,0 +1,83 @@ +/** + * Test for getTagAwareFilePath utility function + * Tests the fix for Issue #850 + */ + +import { getTagAwareFilePath } from '../../../../scripts/modules/utils.js'; +import path from 'path'; + +describe('getTagAwareFilePath utility function', () => { + const projectRoot = '/test/project'; + const basePath = '.taskmaster/reports/task-complexity-report.json'; + + it('should return base path for master tag', () => { + const result = getTagAwareFilePath(basePath, 'master', projectRoot); + const expected = path.join(projectRoot, basePath); + expect(result).toBe(expected); + }); + + it('should return base path for null tag', () => { + const result = getTagAwareFilePath(basePath, null, projectRoot); + const expected = path.join(projectRoot, basePath); + expect(result).toBe(expected); + }); + + it('should return base path for undefined tag', () => { + const result = getTagAwareFilePath(basePath, undefined, projectRoot); + const expected = path.join(projectRoot, basePath); + expect(result).toBe(expected); + }); + + it('should return tag-specific path for non-master tag', () => { + const tag = 'feature-branch'; + const result = getTagAwareFilePath(basePath, tag, projectRoot); + const expected = path.join( + projectRoot, + '.taskmaster/reports/task-complexity-report_feature-branch.json' + ); + expect(result).toBe(expected); + }); + + it('should handle different file extensions', () => { + const csvBasePath = '.taskmaster/reports/export.csv'; + const tag = 'dev-branch'; + const result = getTagAwareFilePath(csvBasePath, tag, projectRoot); + const expected = path.join( + projectRoot, + '.taskmaster/reports/export_dev-branch.csv' + ); + expect(result).toBe(expected); + }); + + it('should handle paths without extensions', () => { + const noExtPath = '.taskmaster/reports/summary'; + const tag = 'test-tag'; + const result = getTagAwareFilePath(noExtPath, tag, projectRoot); + // Since there's no extension, it should append the tag + const expected = path.join( + projectRoot, + '.taskmaster/reports/summary_test-tag' + ); + expect(result).toBe(expected); + }); + + it('should use default project root when not provided', () => { + const tag = 'feature-tag'; + const result = getTagAwareFilePath(basePath, tag); + const expected = path.join( + '.', + '.taskmaster/reports/task-complexity-report_feature-tag.json' + ); + expect(result).toBe(expected); + }); + + it('should handle complex tag names with special characters', () => { + const tag = 'feature-user-auth-v2'; + const result = getTagAwareFilePath(basePath, tag, projectRoot); + const expected = path.join( + projectRoot, + '.taskmaster/reports/task-complexity-report_feature-user-auth-v2.json' + ); + expect(result).toBe(expected); + }); +}); diff --git a/tests/unit/task-manager/tag-management.test.js b/tests/unit/task-manager/tag-management.test.js new file mode 100644 index 00000000..8ee0dbdf --- /dev/null +++ b/tests/unit/task-manager/tag-management.test.js @@ -0,0 +1,115 @@ +import fs from 'fs'; +import path from 'path'; +import { + createTag, + deleteTag, + renameTag, + copyTag, + tags as listTags +} from '../../../scripts/modules/task-manager/tag-management.js'; + +const TEMP_DIR = path.join(process.cwd(), '.tmp_tag_management_tests'); +const TASKS_PATH = path.join(TEMP_DIR, 'tasks.json'); + +/** + * Helper to write an initial tagged tasks.json structure + */ +function writeInitialFile() { + const initialData = { + master: { + tasks: [{ id: 1, title: 'Initial Task', status: 'pending' }], + metadata: { + created: new Date().toISOString(), + description: 'Master tag' + } + } + }; + fs.mkdirSync(TEMP_DIR, { recursive: true }); + fs.writeFileSync(TASKS_PATH, JSON.stringify(initialData, null, 2)); +} + +describe('Tag Management – writeJSON context preservation', () => { + beforeEach(() => { + writeInitialFile(); + }); + + afterEach(() => { + fs.rmSync(TEMP_DIR, { recursive: true, force: true }); + }); + + it('createTag should not corrupt other tags', async () => { + await createTag( + TASKS_PATH, + 'feature', + { copyFromCurrent: true }, + { projectRoot: TEMP_DIR }, + 'json' + ); + + const data = JSON.parse(fs.readFileSync(TASKS_PATH, 'utf8')); + expect(data.master).toBeDefined(); + expect(data.feature).toBeDefined(); + }); + + it('renameTag should keep overall structure intact', async () => { + await createTag( + TASKS_PATH, + 'oldtag', + {}, + { projectRoot: TEMP_DIR }, + 'json' + ); + + await renameTag( + TASKS_PATH, + 'oldtag', + 'newtag', + {}, + { projectRoot: TEMP_DIR }, + 'json' + ); + + const data = JSON.parse(fs.readFileSync(TASKS_PATH, 'utf8')); + expect(data.newtag).toBeDefined(); + expect(data.oldtag).toBeUndefined(); + }); + + it('copyTag then deleteTag preserves other tags', async () => { + await createTag( + TASKS_PATH, + 'source', + {}, + { projectRoot: TEMP_DIR }, + 'json' + ); + + await copyTag( + TASKS_PATH, + 'source', + 'copy', + {}, + { projectRoot: TEMP_DIR }, + 'json' + ); + + await deleteTag( + TASKS_PATH, + 'copy', + { yes: true }, + { projectRoot: TEMP_DIR }, + 'json' + ); + + const tagsList = await listTags( + TASKS_PATH, + {}, + { projectRoot: TEMP_DIR }, + 'json' + ); + + const tagNames = tagsList.tags.map((t) => t.name); + expect(tagNames).toContain('master'); + expect(tagNames).toContain('source'); + expect(tagNames).not.toContain('copy'); + }); +}); diff --git a/tests/unit/utils.test.js b/tests/unit/utils.test.js index 6cd0962f..fc22b7c9 100644 --- a/tests/unit/utils.test.js +++ b/tests/unit/utils.test.js @@ -22,10 +22,26 @@ jest.mock('fs', () => ({ })); jest.mock('path', () => ({ - join: jest.fn((dir, file) => `${dir}/${file}`), + join: jest.fn((...paths) => paths.join('/')), dirname: jest.fn((filePath) => filePath.split('/').slice(0, -1).join('/')), resolve: jest.fn((...paths) => paths.join('/')), - basename: jest.fn((filePath) => filePath.split('/').pop()) + basename: jest.fn((filePath) => filePath.split('/').pop()), + parse: jest.fn((filePath) => { + const parts = filePath.split('/'); + const fileName = parts[parts.length - 1]; + const extIndex = fileName.lastIndexOf('.'); + return { + dir: parts.length > 1 ? parts.slice(0, -1).join('/') : '', + name: extIndex > 0 ? fileName.substring(0, extIndex) : fileName, + ext: extIndex > 0 ? fileName.substring(extIndex) : '', + base: fileName + }; + }), + format: jest.fn((pathObj) => { + const dir = pathObj.dir || ''; + const base = pathObj.base || `${pathObj.name || ''}${pathObj.ext || ''}`; + return dir ? `${dir}/${base}` : base; + }) })); jest.mock('chalk', () => ({ @@ -72,7 +88,9 @@ import { taskExists, formatTaskId, findCycles, - toKebabCase + toKebabCase, + slugifyTagForFilePath, + getTagAwareFilePath } from '../../scripts/modules/utils.js'; // Import the mocked modules for use in tests @@ -119,6 +137,8 @@ describe('Utils Module', () => { beforeEach(() => { // Clear all mocks before each test jest.clearAllMocks(); + // Restore the original path.join mock + jest.spyOn(path, 'join').mockImplementation((...paths) => paths.join('/')); }); describe('truncate function', () => { @@ -677,3 +697,51 @@ describe('CLI Flag Format Validation', () => { }); }); }); + +test('slugifyTagForFilePath should create filesystem-safe tag names', () => { + expect(slugifyTagForFilePath('feature/user-auth')).toBe('feature-user-auth'); + expect(slugifyTagForFilePath('Feature Branch')).toBe('feature-branch'); + expect(slugifyTagForFilePath('test@special#chars')).toBe( + 'test-special-chars' + ); + expect(slugifyTagForFilePath('UPPERCASE')).toBe('uppercase'); + expect(slugifyTagForFilePath('multiple---hyphens')).toBe('multiple-hyphens'); + expect(slugifyTagForFilePath('--leading-trailing--')).toBe( + 'leading-trailing' + ); + expect(slugifyTagForFilePath('')).toBe('unknown-tag'); + expect(slugifyTagForFilePath(null)).toBe('unknown-tag'); + expect(slugifyTagForFilePath(undefined)).toBe('unknown-tag'); +}); + +test('getTagAwareFilePath should use slugified tags in file paths', () => { + const basePath = '.taskmaster/reports/complexity-report.json'; + const projectRoot = '/test/project'; + + // Master tag should not be slugified + expect(getTagAwareFilePath(basePath, 'master', projectRoot)).toBe( + '/test/project/.taskmaster/reports/complexity-report.json' + ); + + // Null/undefined tags should use base path + expect(getTagAwareFilePath(basePath, null, projectRoot)).toBe( + '/test/project/.taskmaster/reports/complexity-report.json' + ); + + // Regular tag should be slugified + expect(getTagAwareFilePath(basePath, 'feature-branch', projectRoot)).toBe( + '/test/project/.taskmaster/reports/complexity-report_feature-branch.json' + ); + + // Tag with special characters should be slugified + expect(getTagAwareFilePath(basePath, 'feature/user-auth', projectRoot)).toBe( + '/test/project/.taskmaster/reports/complexity-report_feature-user-auth.json' + ); + + // Tag with spaces and special characters + expect( + getTagAwareFilePath(basePath, 'Feature Branch @Test', projectRoot) + ).toBe( + '/test/project/.taskmaster/reports/complexity-report_feature-branch-test.json' + ); +});