From e8bf26b07088198564c9d1a106d86725c5673909 Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 01:31:06 +0200 Subject: [PATCH 01/11] feat: Agentage Memory VS Code extension v0.0.1 Connect VS Code to your Agentage Memory in the cloud and search it over MCP. - One command (Agentage: Search Memory): live search-as-you-type over memory.agentage.io/mcp (Streamable HTTP), opens the hit read-only. - OAuth 2.1 + PKCE + DCR sign-in; token in SecretStorage; loopback callback. - Gear (settings) + sign-out buttons in the search box; agentage.mcpUrl setting. - esbuild bundle, vitest unit tests, dual-registry (Marketplace + Open VSX) CI. - Official agentage rocket-A icon. --- .github/workflows/ci.yml | 20 + .github/workflows/publish.yml | 29 + .gitignore | 5 + .vscode/launch.json | 13 + .vscode/tasks.json | 20 + .vscodeignore | 14 + CHANGELOG.md | 15 + CONTRIBUTING.md | 44 + LICENSE | 21 + README.md | 62 + esbuild.js | 31 + media/icon.png | Bin 0 -> 25163 bytes media/icon.svg | 29 + package-lock.json | 6981 +++++++++++++++++++++++++++++++++ package.json | 92 + src/auth.ts | 148 + src/config.ts | 14 + src/doc-provider.ts | 17 + src/extension.ts | 31 + src/mcp-client.ts | 108 + src/search-core.ts | 49 + src/search.ts | 95 + test/search-core.test.ts | 78 + tsconfig.json | 17 + vitest.config.ts | 8 + 25 files changed, 7941 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/publish.yml create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 .vscodeignore create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 esbuild.js create mode 100644 media/icon.png create mode 100644 media/icon.svg create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/auth.ts create mode 100644 src/config.ts create mode 100644 src/doc-provider.ts create mode 100644 src/extension.ts create mode 100644 src/mcp-client.ts create mode 100644 src/search-core.ts create mode 100644 src/search.ts create mode 100644 test/search-core.test.ts create mode 100644 tsconfig.json create mode 100644 vitest.config.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a3d1cf5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run check-types + - run: npm test + - run: npm run compile diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..4f59110 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,29 @@ +name: Publish + +on: + push: + tags: + - 'v*' + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: npm ci + - run: npm run check-types + - run: npm test + - name: Publish to Open VSX (also produces the .vsix) + id: ovsx + uses: HaaLeo/publish-vscode-extension@v2 + with: + pat: ${{ secrets.OPEN_VSX_TOKEN }} + - name: Publish to VS Code Marketplace (reuse the same .vsix) + uses: HaaLeo/publish-vscode-extension@v2 + with: + pat: ${{ secrets.VS_MARKETPLACE_TOKEN }} + registryUrl: https://marketplace.visualstudio.com + extensionFile: ${{ steps.ovsx.outputs.vsixPath }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fe02ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +*.vsix +.vscode-test/ +*.log diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3c25536 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/dist/**/*.js"], + "preLaunchTask": "npm: compile" + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..dc96bc3 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "compile", + "group": "build", + "problemMatcher": [], + "label": "npm: compile" + }, + { + "type": "npm", + "script": "watch", + "group": "build", + "isBackground": true, + "problemMatcher": [], + "label": "npm: watch" + } + ] +} diff --git a/.vscodeignore b/.vscodeignore new file mode 100644 index 0000000..7e9f0df --- /dev/null +++ b/.vscodeignore @@ -0,0 +1,14 @@ +.vscode/** +src/** +test/** +node_modules/** +esbuild.js +tsconfig.json +vitest.config.ts +vitest.config.* +**/*.ts +**/*.map +media/*.svg +.gitignore +.github/** +CONTRIBUTING.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4432866 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +All notable changes to the Agentage Memory extension are documented here. The +format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and +this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.0.1] - 2026-06-21 + +### Added + +- `Agentage: Search Memory` - live search-as-you-type over your remote memory, results show title, path, and matched line. +- Open a hit as a read-only Markdown document via the `agentage-memory://` scheme. +- OAuth 2.1 + PKCE + Dynamic Client Registration sign-in; token stored in VS Code SecretStorage. +- Settings (gear) and sign-out buttons inside the search box. +- `agentage.mcpUrl` setting to target a different stack. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9f40b30 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,44 @@ +# Contributing + +## Develop + +```bash +npm install +npm run compile # bundle to dist/extension.js (esbuild) +npm run watch # rebuild on change +npm test # vitest unit tests (pure helpers) +npm run check-types # tsc --noEmit +``` + +Press **F5** in VS Code to launch the Extension Development Host, then run **`Agentage: Search Memory`** from the command palette. + +Point at a non-prod stack while testing via the `agentage.mcpUrl` setting. + +## Architecture + +A thin [MCP](https://modelcontextprotocol.io) client over `https://memory.agentage.io/mcp` (Streamable HTTP). It calls two of the six memory tools: `memory__search` and `memory__read`. OAuth 2.1 + PKCE + DCR is handled by the MCP SDK's `OAuthClientProvider`; the loopback redirect is captured on `127.0.0.1` and the token is stored in `SecretStorage`. + +``` +src/extension.ts activate(): one command + read-only doc provider +src/search.ts QuickPick: debounce + cancel-in-flight + sign-out button +src/mcp-client.ts MCP Client + StreamableHTTPClientTransport (connect once) +src/auth.ts OAuthClientProvider backed by SecretStorage + loopback callback +src/doc-provider.ts agentage-memory:// read-only document provider +src/search-core.ts pure helpers (the vitest-tested surface) +``` + +## Package a .vsix + +```bash +npx @vscode/vsce package # agentage-memory-.vsix +npx @vscode/vsce ls # confirm only dist/, README, LICENSE, CHANGELOG, icon, package.json ship +code --install-extension agentage-memory-.vsix +``` + +## Release + +Publishing to the VS Code Marketplace and Open VSX is automated by `.github/workflows/publish.yml`, triggered on a `v*` tag. Bump `version`, update `CHANGELOG.md`, dogfood the `.vsix` in VS Code and a fork, then: + +```bash +git tag v && git push --tags +``` diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b68dd64 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 agentage + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6e6bac8 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# Agentage Memory + +> Connect VS Code to your [Agentage Memory](https://memory.agentage.io) in the cloud, and search it - read-only, over MCP. + +[![VS Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/agentage.agentage-memory?label=VS%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage-memory) +[![Open VSX Version](https://img.shields.io/open-vsx/v/agentage/agentage-memory?label=Open%20VSX)](https://open-vsx.org/extension/agentage/agentage-memory) +[![Installs](https://img.shields.io/visual-studio-marketplace/i/agentage.agentage-memory?label=installs)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage-memory) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) + + + +This extension connects your editor to your **cloud memory over MCP** - the hosted Agentage Memory endpoint at `memory.agentage.io/mcp`, the same memory every AI you use already reads and writes. One sign-in, then search it from the command palette. No local copy, no API keys. + +## Features + +- **Connect to the cloud MCP** - one-click **OAuth 2.1** (PKCE + Dynamic Client Registration) sign-in to `memory.agentage.io/mcp` (Streamable HTTP). The connection is the product; everything below runs on top of it. +- **Search your memory** - `Agentage: Search Memory` runs live search-as-you-type; each hit shows its title, file path, and the matched line. +- **Open read-only** - press Enter to open a hit as a read-only Markdown document. No writes, ever. +- **Point at any stack** - a gear button in the search box (and the `agentage.mcpUrl` setting) lets you target prod, dev, or self-hosted. +- **Sign out** - a button in the search box disconnects and clears the token. + +## Requirements + +- An Agentage Memory account. The first search opens your browser to sign in. + +## Getting started + +1. Run **`Agentage: Search Memory`** from the Command Palette (`Ctrl/Cmd+Shift+P`). +2. The status bar shows the sign-in host and your browser opens - approve the connection to `auth.agentage.io`. +3. Back in the editor, type to search; press **Enter** on a result to open it. +4. Use the **gear** button to open settings, or the **sign-out** button to disconnect. + +## Authentication & privacy + +- Sign-in is **OAuth 2.1 + PKCE + Dynamic Client Registration** against `auth.agentage.io` (opens your browser; the redirect comes back to a local loopback port). +- Your token is stored in **VS Code SecretStorage** (your OS keychain) - never in settings or logs. +- Only your typed query and the path you open are sent to the MCP endpoint. +- **Read-only. No writes. No telemetry.** + +## Settings + +| Setting | Default | Description | +| --- | --- | --- | +| `agentage.mcpUrl` | `https://memory.agentage.io/mcp` | The cloud memory MCP endpoint (Streamable HTTP). Point at a different stack here. | + +## Compatibility + +VS Code, and forks via [Open VSX](https://open-vsx.org/extension/agentage/agentage-memory): **Cursor, Windsurf, VSCodium**. + +## Known limitations (v1) + +- Search is literal substring (`git grep`), not semantic. +- Each keystroke is a live network round-trip (debounced, prior request cancelled). +- A single memory is assumed; multi-vault selection lands later. + +## Links + +[Homepage](https://memory.agentage.io) · [Repository](https://github.com/agentage/vscode-memory) · [Issues](https://github.com/agentage/vscode-memory/issues) · [Changelog](./CHANGELOG.md) + +## License + +[MIT](./LICENSE) diff --git a/esbuild.js b/esbuild.js new file mode 100644 index 0000000..863d5d3 --- /dev/null +++ b/esbuild.js @@ -0,0 +1,31 @@ +const esbuild = require('esbuild'); + +const production = process.argv.includes('--production'); +const watch = process.argv.includes('--watch'); + +async function main() { + const ctx = await esbuild.context({ + entryPoints: ['src/extension.ts'], + bundle: true, + format: 'cjs', + platform: 'node', + target: 'node18', + outfile: 'dist/extension.js', + external: ['vscode'], + minify: production, + sourcemap: !production, + sourcesContent: false, + logLevel: 'info', + }); + if (watch) { + await ctx.watch(); + } else { + await ctx.rebuild(); + await ctx.dispose(); + } +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/media/icon.png b/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a10ddc3b7cb47e0b2fa6f5e185a329ac04892d57 GIT binary patch literal 25163 zcmV*3Kz6^0P);Tk_9o;0$c)SvFJ44OR#kUbb0Kr+Ec<3 zEys|qF2_^EVbBXjPw;T5f3SXssQR<(L?WmetwohP5Y9}%}d z4Ag&5tqrLQ&pqY981UA5L*1~lqOM$A(c71nH5ONZ#bsb|1z1h|eSAV!L;R zQ$|h&zFx*CUOR4HE>t@pSq1&q~!W<#MprqF2u?J*o} zD)pTer9U^bI`-*D9(n4?z8kbg)Y#|-5Ncd{&c2(wE&PkQ6A18~uKdk-{gwI5Fs{hnj< z$q93d37$JLtbs`!m4)`+yHg<^tr30DwdTN9Qz-&S{J_aKY}b`n}7}+xIIP$$yzyRsZ49N1s2mQEgjq15mqa|K2+^ z@UM@|t?oZ~G_{nYOl6?=C3=Qm3Ewe)|US=4WS>X063;QPQCR%gzs zKtg$sD^|kcGHB;e<^VlpdF2O@k;#?nlni39?Yyt#n**SVGeMZQ|9y21F|8&V&mY!! z>gCmomB!tdoW1u~u!i_Fv?dY2g=e4ss#at5Q&Y$EfkQJ1^l0MVRy>w2B`7~fni|l` zpu!sW24o-)F|RH0s*RzrytT;*JOXr7f*JzNBLj1mrfR}RIW#LWiqnIIW#EaIlIBU< zYQK8|78hEOQr^DO$ADGrZZ9^P-;mUvK-jGq zqZT@d*-b0MbRC}}(1k-NSknV%YA{06f+PW+I+&>QPf#K)l^zzXJE6{I0W&7CI zU;XO6Z+ral=bssb+`gs&7o2t4tJ~eiUC&G<7apA-EzfU-jx>#36lv^Ch$o%UQvp(F zFSZ46Lv|q5A9DC2cE8X89WmlrTP?#tqLf`4PlO5ck}J0)CMY3HlPiD*^CM zrQ%^0$_Dq(nfQAeR%#Sz9|r&^8UtT{qmaiXL>mI34Z}!tiyF@!O3vukmcDe(IcNM( zzw&xA02lnwi6^z2EC2A!A${`PB8j6U4^Z`3Lpj#E6V)qHrbttOPG^?99AC?#Z>uP1 zS1y$eSC$X(A{iytDsT+GpVNC1>O%TAL@`l9ZeP50XU2fcC!8_RD2#WWmX4!kLzrAT z-LS@UNcDMcQRC^ClhY^E@>ef@)xNWXonJzg4Zu0)oG{sGH~#V2DgCOs5n1V%Jhwj- z410Xp6BpjzS9j>=z(K$RvPbTLfJHoQ#+Ze1XDl*{KoXFEff_G{Vtqa3T^UE4f zA4>K%n)-|9oOasYUgcC;1Uw68wN7l$ed(3i1w~Lq-IB#{%CM=re;*w(hE6`!RTsC)16^*;Ja-M0a1a;vGU^XH}zh! zoa!ppUq73YPJ6syrKJq3wyvlguMCfTnl|N=W0h5Tu4arT)$DZCAAHvs7c;=Ih2*Tg z+iIVF9=H)erPcW8DZnLX?Yn(xS^xMbJm=?Oo)z(B7qQ`faiOzN-^I98mP(gH*@#eC z*@t2EO%ZvWYjGIzO>v=wcKhy+_Cajlc|!D@S6DFgmo26Rv@)(Q!#*WAJgaedPQUGv zbNBwIs%4`L!2VaCdKMbVA3QUqqt=%;@&M9kP*hMds_CpfzjVsv<&=gd3gv)~m37Kn zbr)(awwhc)}pVutE=lpGdZ(q>F@`!+?(Xvj>HY3-GVU7l#olc-?_^pf1 z*?UfGnNkCA;OyyNnVQiT%?|O3zXW7@kq%-pls*6#7xJop2>5QB{IIVAdcX!d$lp@n z2B^wt#ux}GYLM>5ksas@Gj6{1mUu&;QDs_?*I1%c!$ye)o;#FGjMeZd0An#_f(GF1 zvrm6j0`;#B9UI4QYFX)AQiKtPj z0?0v=?eHeZLFpLGfJicJ_As1)zxpk zaAf$vpM#5B(+kB?W4wMyexBy=xqis^#$P|6_dN;>ky@i8rs5dGBpCw;ed3et$`TAP zFD@Dppe!1o35qe%>|t9RTv`F9XZ33ioO8-Ag!n`QaLL&xedNfjK4aMS@beBpHsTcg zlA$R0C_?S4aIX&Fl^iKavh05HOv!jTE(<{L zNr6>^tz*M#1hfWTJd$)9h7l8V50?k5uTR)qxcg9LcL zmdh^&=k<9Ru9!Y0kDdcZ06s)=q^>jGa? z4!DZw+(T8+#{%91aQQ9qe#w<783wPeX5WQisIfqI34$d~7b+z0vURAN+Eu-9?K8jEfg<{7Wx1w^Qtd1N)RYq~5X#>D5?@H4`vbB?s;W9?k(ZOSs-W~@uK2ii=n(gF6WNOPSxNV_{6GRV*b8tX!CD^8i zx5qUCu#5oBC|rq=ShS}+MmKxP0gIOmkh<`b{MmF>1yYL96(?Gt}}uAH!k_eK$wsQ+j!{i|J& z*>>295O{Q8`ht#^BOfa2ptK&yaslNilnNM!{d z;6FpAl~KMp8qDPUm068$XZ2$M3Iotq$y;7r7>NAJR6b{NJ%1VaMS0m(3~xS|PI{40W7ObH3djaP(hPwelD8TokdRexG*K269fGQH}| z@gcAJYtvC$SgT>>93#M1{@rzfVsTI*emX!KX&V7;O-HQqSU;LsOi-)W-V6Y>*7)j0 zi_7a+J8T7s1%JU834YZ-_<5W2x;){2$m4StC^|~wMSajz)?t1E%MVF-NKOgmjCMUL zZ$(%REy|g!q+F2y=i2^pQ8_SU#uAXneh`s>pU)EsR512~pdyhmFeV!(i4Luo1tEFC7$cK9$(bQwX zVBN+bC>9A5+$2dzt{Q(iuRMgnwW5$7g3^<%*+(!#PveN|oB z7^~x~g>_m0j9T;?B=`lzqL27|ZL{lEOsdSEma(H3aXf{(L8WU^1_i4;=>m&3u!>(?w*8Dz2X;Ar%h8N7&@1mnBvnx^LB8>{#*Rqh=r~DXz10*2 zK&gCsAQ}R}TbqW^Xc8#KfW8BuO$J{VC~Sk(HuHplx24Poxbt`orxPV>C-}Ryv;m36 zWCLpLA^_?QY|s`dQHy@D;AebQ!QZdf55KhrZ#l~1BSrp(9vjBm0vZ5pA6GbWTO9!K z^3heiGUr!2D@PTFVwqfm6B#ftE5;}q0s+*yDB|70%DBK5jDVMy83A)$!3dHwiv@JnC|FZQuKhd1E$1@KbCB9;l1b!AA2@nDze zlwEcF_!~QT(Ik%Ok{851>OlFP1 z0V+wPfJyt4{wC1%$SEMxQohAOP2~1t1dJrF5y;Q|MqsThfYxX>%Gr7&zj6}rdkusu z!v}uOn0B;KzDMwMXTW#ZJizCM#mN_@Ix%t$HEIe!_2xD{e0>Lvn#{RxR~;XI zeI4(=rj0-P(ma0ei}P4Xv;$bFnNEZNxQm1|Te%`_Ly+l<4o?dlgUp^3_}2wwBVhB% zMj&693mE~{=CGHS(cX`tFQZ1c1)MO^zloV_1N1gZ!EG?CZJx<|LZV&oUjl4P4%tD) z8}@@O9|;C%qD|}duS>W>NM9h`@y3jN5cmR`XwpR6&TwV9+fo^7k16~g@0rA(lhJ$<-eT4{EE@|g1WRlj4ZIQL|$T|1xWF(GnE$VqQFl3Sy>sh1Q(&5 z|5LK`hn2JBS+WWSlRVir>8ju%a@@BXwOH36b_6o*F>-c}YcysTF_4``fMUlI#eteD zYRLN+zX+R}MfwIDI8UbDM*js%UDTECEEMbcL-YNqS-brb@FcHqGiV$R?d0P%QY>9* z9G+J>mj!k)I!F_13i#h|j|V@c%U;#QFWfwd|M5?bA<@dJ570O~Piph%sFUn~N#pRW zD$=}$Aa&(jo+kfI&l3JjDI9(axS957yFJshit)km@Rlr9JRU6CobF8J$|3g(kh)Xp zt`Qi_jzCn-wyp|)9=sRwH?bW2rh%pNe)v6qDX3$?AGIAcGNYw(A&T*vEXiOfRzN{0 zZ|cnDm{)Am!BeKGI6}yW zYk8n`K#twEGVp6_aGb579GUWfvn;EO5BN@50rW~`fER#XfR&6Taks;*w zN`s349B{L46gtayQ??9Z6Ithpk6J_{GC1(lLc(m)-XMY4F+s(=fN={JhdRv4Kp8xaj8ycA0GX zap0$k+?aU5FVt6nvjq6`T+z@zOEWPi1G@z>1$3GU@4sg4e(3qZ*R}H}0+zuGwcWW- zVhB`WID&o1+TouP^kxJ^)e@D$CTBlTt1hC;l&3@{Ej0+ROVj|!8%!06TR+W~>D_$f zgP6a2<*{`6@2!u!X5Ao8SJ&b?jc32C^D%mad~qEn9v!dr5kUt|qwH*0v` zYuA38hY!B4gLX?*Xe*x{2oaE(7KEaKEL|K2hc^@nXiH{LXEFwfhuSmN49AW;`GkSr z1G^D9zfbDf0Qhd$$`{VPva%B;j-q@m8;}z4Tj$*Kl1tCrFG}eMuUY6a#vsq5ithtH z+-spp^9_Ak==x5FqOdt8eVS^EwJ)Jmkno2%#k- zz~qZYAi(1`(7yIP6_BV5KR&}%l?M74(CQwcBZ?&Vv)vZ>eXIW2xi{od5#T2S@3t!p zemH!dHX2Zaczu&@dHn$Jm3xg0IADOM{GF!4d)LAH8@lbP^oc-jkYXa3{G8su@C1ZM z1Ezmz0|WrX7y*0yY)25(AxCiw2|+^=ctL0*qkx_a0BuCjI`x<@@+uqrzOX(MAX z6>po zS-Ywl0qLtvUgCO_U4*6rIRmd>IIo;9+|poj`W z;5WA^Obe)p{7Hci+~)=g{8+ zSewTkRA&%NWLXP+Fv=e3^^KgYlJH`n{HEZ$uUy-ee;;ihSGeW!mZz<0zlerF><9Wn zkuW7N;}mHGAo9gc6=U>;Q*bI^7()5zF~3KHP+432jqq3nt0RSH?<%)x!Sd0ezekiZ z^-D4Yi|!}@Vc?3v=lf~8`2w&}YL(06fX~l;z&G+7(5u{Yb{gpqbvBCLe@zGDEeLIN z4T0_XvwYArv(^DPQ-ZQ}fxx)gr#>U#Ula`Mb|HgL1*G!gf*`RF;qvl(0lnCOMz;m* znTRi-ghnf*JHwbp^Id)n_(TwqPBe0)d~N{pzVcXe+Me`}9Ny6csZ9Y@oxuPAAOJ~3 zK~&uqlS3cP8{Q_X}QS%hBmO8uWbuBZog9*ZF_+ zbpfhblt*K{U7*>LLoPH?cFppQg z&V&mYk^rno;-OiWR|2OEw4$SpN1U3W`62Hg4&@HbnRD&s34!0FPt7qN5b&b_H3vU6 z4mALW=U{n1Bhm7RxqKV=w4aX5+wEyL72bK-#(953w_MS|Uw(ZN^GiAhcgPUv{PnrC z&koNQ3T!s!q#&n8AkT+u1k8BF837sKCqU!SY`hVW@)ZC~0EcGmI?ZOHrtKjR)BZB} zDqbEc?%Q`i5*fU2>sFlth#`xYtu!qs5<2?|l!pGEq9Fqz&HJ5me$OZYzjDD}ObcxA z(-67f6~cVjPZf&1^tk2n7Iti)_cyeCT;Zkz*;)Yjbf&m3uzLVh@v&B+ujsmfZD2EA zRG1DpJXPKs@er>kMwbI9t%RRQO!_EVYy6FJL1Yq&w1~OCP*1p@`~znT^33}s@Oz9* zDfpF9aFdpSpC5T0fq8zO#()o5R;Q_O`v%VaIlb?iY}X)|b_<38?tO?0q&etKf3Uvp z#R!Nz{`CNx(I-PjU1&kDNGlp>gV?_opvYMzVn($_*NT_xA(WXFdeOENrsyyVtx0(g@acJWee>n*q455OwvQ{k>p-h$Z+D0!(9~6ASAk2szTtI%Ux2ASmi`=fSm}fLsUzjsrV1&%~SR@X{%Jm zNlSz@ure52z7q0%*NVxoUh>JF%czXcpLp2?H|2=}Eu-tL+L&*N0C1M*bB z|1ue6i;DuJ28dBWs0i2bNUu+++yGPtxFPK?%Mk7ZUx=y7z?PM_6^ijwZ)GWAdLb!v z8Tdi?squgTJ`HaTuSykADLu4ve@;8QHT=kB%>v+Q=ZN>NbE6k;1d8c}kO%W$@t2OR zr7ME2Y5P(<50ww*OLBaeP(`K$@>m1mqo5X*S-FsLC?k1opg->qpZDhrf1Uy318sTg zEJUT6%MAlU;8z9&un#Jq&GR|%&D{T%D~9K}e;M6=bsL>A+9yh$66A;JBiRU0qhSNx z%YbRy}#5TTHdj!l+T3ka22+w zA`E`YoAZ#lK8P~so{X*;D24Wz!aFV<{<%M=+pcP(Jw{jU4Jefj)Cxv`_rGgUi$y^` zrgW?=?QlTce-yyU8wC)tzUJgNvD`V-|w0EH2N z#bd9N6hq@iXtW2l5d9_IbaU4l5KC%u-0FRm5xZc0) z+5#)7+X?+k=KV_917Q?4SMCV#+xfQFH$3gJbkmJdrQ5G;qcbLfJnJXGF#=GupWL65 zOP-&ORsLu&&nLzhqz>B9G7#q%+D&rU?3~zXfJo+kqIu)$D0L_0;DguFIceH&CH;$k zB&`JCWo?MP7xTvsDP_Rt3sVyKg|c4H54!OMd9f(tdFO!^wvW)D;LL zOj_jJKTpfrnJbMppd`$y5a7)F0XWa0EyDm2{7^+b1_)f4+f9X=N7(xty6wv1?Lhkn zQ~@JE`Wzre0QMMw@fBmko(hmC00nDF6wuoWyTlYLCw3a(W=2>bLXB=)W6y+bc0`@0 z01^aFbO65kUnsa+me--Pya~D^kW#6l=y2I0uegtVM zsZD7m~RXqFj>lJ;A2$$9yXKpey&DrIsRq#|xuRw3*v zX+uyB4+C;*WUU_M`MIZNhJt!~%Ii!6cwTNugs%fD;Kobao5K4W+S#q)?Uy#~dk2c| zDtZhlvcJB0er85(OP^a(f)qa9EQw|LNnr5GVagr97}$ei`&c}@6*Nmpf5PoiQEjYF zieG9cQ@U}*uFa+RVv6rvc{){5dE~DyJUk>h3UIc$%DsOLH(fURbAL{^UfD)_49pO6 z11Y>Qh$0{CTpFYBx!_>9zB;;2&mvaq`XryeihS}(DLDq9Cu<0RKK^s~wUA~ke@y+A ztZgKpl*qk5XI9dxzhBw%g$}W&4-x^b!()$~_^{O`7jck$E7)cS_9tDgrz~Z@e z$WH_$>PPn^kOwJ}w-h50a^hbEs>+msE2fCskpaO@mK**{m!(D_H^_PZl}{@omOTyN;0J&kFWsEp-%t?+ATxxdZ#lU6R3K=0l|S8tqMGN~6b2DZs4@+( zGvkei3d@ZEYKX_rtu1!4m=X5Lmr67G-#Ok;7KNYhe$j?D_EFU00@+1lZ!<`2Babf2K zjYk#d7NQbZ^!{OxQsdwwL1=k?U)1(K462p+|i>rOZF|5Wkk9hbDQ zeFT5;*DLMp*6_BAT6W)f9?O<_eo8!I3mXaHM?xX-L6FBJ`bm~s3bvlB6g90XP%9Y+ zPhMr~7THM2ILPJwkN%`{QK7W0Oja2Ufd5tiw!>>Tx0d%e^zN(LXpWhVke{37M%xnw zNM+=6g{Z|l56DFdFjms*3b^STqZ!r8xm-&cO`d6rFa$y2<(;VPwAe>( zA&$aQk0ylv<^2uq?AGvx{q$=>+KB>ks$h_f@AOUydYA?%p5PHt1?0hI zluz|t(IFtPq{@2&x)gW;2yF05DG=<49$U@}4v6t25CF{!Mkro>&FB8H<+Jmx>irG< z$bmLmjhF~b$%v^kRuBvZ8M`PzTM2QG163$f;t%0h3H5sG^wWmAn`*|PqNVjPC?U-o z{*yA2hq1hhmrwBiAl^Sqf5#T}{)V=Xr%wbzQ9xXO7v~OH=!saoD^aeV^pW#dEihop zHEs|$AIcqQ$3zM%Wn(XdxKTmLn_}jiKlk_X<>$7sX^knoa|?TaL$_WT5d{Fq-wP<= z^GyRR-V!Got+xTjK{&cl1wA>zjC%VvUCr^&gB zZX@qSU!AEqvi#vujYH zFNp@({Nd4+rvk#y4$mFLs?Cfc@KL(WHVNxrl}N4LYuDOYZ2 zgAkK9(Gl81`N&@-Rm>8?Q;NOQ1LplTpd#kt9wo&y6l*u)1Fl�N1!Uijf0RUW(D%3av}DLRa@QB@3h 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 KMNUMnLSTZ~jE%bh literal 0 HcmV?d00001 diff --git a/media/icon.svg b/media/icon.svg new file mode 100644 index 0000000..f9e1144 --- /dev/null +++ b/media/icon.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f6a208a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6981 @@ +{ + "name": "agentage-memory", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "agentage-memory", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/sdk": "^1.29.0" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "@types/vscode": "^1.85.0", + "@vscode/vsce": "^3.9.2", + "esbuild": "^0.24.0", + "ovsx": "^0.10.11", + "typescript": "^5.7.0", + "vitest": "^2.1.0" + }, + "engines": { + "vscode": "^1.85.0" + } + }, + "node_modules/@azu/format-text": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.2.tgz", + "integrity": "sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@azu/style-format": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@azu/style-format/-/style-format-1.0.1.tgz", + "integrity": "sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "@azu/format-text": "^1.0.1" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.2.tgz", + "integrity": "sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.24.0.tgz", + "integrity": "sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.1.tgz", + "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^5.1.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.14.0.tgz", + "integrity": "sha512-Dfl7hPZe9/JJwRhFFXHq2z1oHYBuGubmff3kWXOsd1AGgyXlqjNYAWuN/1JL/ZrcZBs8TKMjGSil6Rcc7E8VPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.9.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.9.0.tgz", + "integrity": "sha512-1MWGjqgUCRAYgLmVFZKp7fs3Rg1TFvIMgywY8ze2olNVvLlJoRThuoziWSDJuwwyJI5L4rnLb9Tyt5D9GvSLPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.2.5.tgz", + "integrity": "sha512-RUuewWk9JvWJS5Yiy8/74Lm1rQAWlrU/qg/Bgtk1jIauVRtnb9XKwS5Xg0J+Whwjesq9EVrBIFgQEP8vHxgezA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.9.0", + "jsonwebtoken": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@hono/node-server": { + "version": "1.19.14", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", + "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.19.9", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + }, + "zod": { + "optional": false + } + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@node-rs/crc32": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32/-/crc32-1.10.6.tgz", + "integrity": "sha512-+llXfqt+UzgoDzT9of5vPQPGqTAVCohU74I9zIBkNo5TH6s2P31DFJOGsJQKN207f0GHnYv5pV3wh3BCY/un/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@node-rs/crc32-android-arm-eabi": "1.10.6", + "@node-rs/crc32-android-arm64": "1.10.6", + "@node-rs/crc32-darwin-arm64": "1.10.6", + "@node-rs/crc32-darwin-x64": "1.10.6", + "@node-rs/crc32-freebsd-x64": "1.10.6", + "@node-rs/crc32-linux-arm-gnueabihf": "1.10.6", + "@node-rs/crc32-linux-arm64-gnu": "1.10.6", + "@node-rs/crc32-linux-arm64-musl": "1.10.6", + "@node-rs/crc32-linux-x64-gnu": "1.10.6", + "@node-rs/crc32-linux-x64-musl": "1.10.6", + "@node-rs/crc32-wasm32-wasi": "1.10.6", + "@node-rs/crc32-win32-arm64-msvc": "1.10.6", + "@node-rs/crc32-win32-ia32-msvc": "1.10.6", + "@node-rs/crc32-win32-x64-msvc": "1.10.6" + } + }, + "node_modules/@node-rs/crc32-android-arm-eabi": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm-eabi/-/crc32-android-arm-eabi-1.10.6.tgz", + "integrity": "sha512-vZAMuJXm3TpWPOkkhxdrofWDv+Q+I2oO7ucLRbXyAPmXFNDhHtBxbO1rk9Qzz+M3eep8ieS4/+jCL1Q0zacNMQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-android-arm64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm64/-/crc32-android-arm64-1.10.6.tgz", + "integrity": "sha512-Vl/JbjCinCw/H9gEpZveWCMjxjcEChDcDBM8S4hKay5yyoRCUHJPuKr4sjVDBeOm+1nwU3oOm6Ca8dyblwp4/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-darwin-arm64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-arm64/-/crc32-darwin-arm64-1.10.6.tgz", + "integrity": "sha512-kARYANp5GnmsQiViA5Qu74weYQ3phOHSYQf0G+U5wB3NB5JmBHnZcOc46Ig21tTypWtdv7u63TaltJQE41noyg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-darwin-x64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-x64/-/crc32-darwin-x64-1.10.6.tgz", + "integrity": "sha512-Q99bevJVMfLTISpkpKBlXgtPUItrvTWKFyiqoKH5IvscZmLV++NH4V13Pa17GTBmv9n18OwzgQY4/SRq6PQNVA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-freebsd-x64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-freebsd-x64/-/crc32-freebsd-x64-1.10.6.tgz", + "integrity": "sha512-66hpawbNjrgnS9EDMErta/lpaqOMrL6a6ee+nlI2viduVOmRZWm9Rg9XdGTK/+c4bQLdtC6jOd+Kp4EyGRYkAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-arm-gnueabihf": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm-gnueabihf/-/crc32-linux-arm-gnueabihf-1.10.6.tgz", + "integrity": "sha512-E8Z0WChH7X6ankbVm8J/Yym19Cq3otx6l4NFPS6JW/cWdjv7iw+Sps2huSug+TBprjbcEA+s4TvEwfDI1KScjg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-arm64-gnu": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-gnu/-/crc32-linux-arm64-gnu-1.10.6.tgz", + "integrity": "sha512-LmWcfDbqAvypX0bQjQVPmQGazh4dLiVklkgHxpV4P0TcQ1DT86H/SWpMBMs/ncF8DGuCQ05cNyMv1iddUDugoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-arm64-musl": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-musl/-/crc32-linux-arm64-musl-1.10.6.tgz", + "integrity": "sha512-k8ra/bmg0hwRrIEE8JL1p32WfaN9gDlUUpQRWsbxd1WhjqvXea7kKO6K4DwVxyxlPhBS9Gkb5Urq7Y4mXANzaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-x64-gnu": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-gnu/-/crc32-linux-x64-gnu-1.10.6.tgz", + "integrity": "sha512-IfjtqcuFK7JrSZ9mlAFhb83xgium30PguvRjIMI45C3FJwu18bnLk1oR619IYb/zetQT82MObgmqfKOtgemEKw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-x64-musl": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-musl/-/crc32-linux-x64-musl-1.10.6.tgz", + "integrity": "sha512-LbFYsA5M9pNunOweSt6uhxenYQF94v3bHDAQRPTQ3rnjn+mK6IC7YTAYoBjvoJP8lVzcvk9hRj8wp4Jyh6Y80g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-wasm32-wasi": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-wasm32-wasi/-/crc32-wasm32-wasi-1.10.6.tgz", + "integrity": "sha512-KaejdLgHMPsRaxnM+OG9L9XdWL2TabNx80HLdsCOoX9BVhEkfh39OeahBo8lBmidylKbLGMQoGfIKDjq0YMStw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@node-rs/crc32-win32-arm64-msvc": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-arm64-msvc/-/crc32-win32-arm64-msvc-1.10.6.tgz", + "integrity": "sha512-x50AXiSxn5Ccn+dCjLf1T7ZpdBiV1Sp5aC+H2ijhJO4alwznvXgWbopPRVhbp2nj0i+Gb6kkDUEyU+508KAdGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-win32-ia32-msvc": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-ia32-msvc/-/crc32-win32-ia32-msvc-1.10.6.tgz", + "integrity": "sha512-DpDxQLaErJF9l36aghe1Mx+cOnYLKYo6qVPqPL9ukJ5rAGLtCdU0C+Zoi3gs9ySm8zmbFgazq/LvmsZYU42aBw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-win32-x64-msvc": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-x64-msvc/-/crc32-win32-x64-msvc-1.10.6.tgz", + "integrity": "sha512-5B1vXosIIBw1m2Rcnw62IIfH7W9s9f7H7Ma0rRuhT8HR4Xh8QCgw6NJSI2S2MCngsGktYnAhyUvs81b7efTyQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@secretlint/config-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-creator/-/config-creator-10.2.2.tgz", + "integrity": "sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/config-loader": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-loader/-/config-loader-10.2.2.tgz", + "integrity": "sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "ajv": "^8.17.1", + "debug": "^4.4.1", + "rc-config-loader": "^4.1.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/core": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/core/-/core-10.2.2.tgz", + "integrity": "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "structured-source": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/formatter/-/formatter-10.2.2.tgz", + "integrity": "sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "@textlint/linter-formatter": "^15.2.0", + "@textlint/module-interop": "^15.2.0", + "@textlint/types": "^15.2.0", + "chalk": "^5.4.1", + "debug": "^4.4.1", + "pluralize": "^8.0.0", + "strip-ansi": "^7.1.0", + "table": "^6.9.0", + "terminal-link": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@secretlint/node": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/node/-/node-10.2.2.tgz", + "integrity": "sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-loader": "^10.2.2", + "@secretlint/core": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "@secretlint/source-creator": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "p-map": "^7.0.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/profiler": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/profiler/-/profiler-10.2.2.tgz", + "integrity": "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/resolver": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/resolver/-/resolver-10.2.2.tgz", + "integrity": "sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/secretlint-formatter-sarif": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-formatter-sarif/-/secretlint-formatter-sarif-10.2.2.tgz", + "integrity": "sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-sarif-builder": "^3.2.0" + } + }, + "node_modules/@secretlint/secretlint-rule-no-dotenv": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", + "integrity": "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/secretlint-rule-preset-recommend": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", + "integrity": "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/source-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/source-creator/-/source-creator-10.2.2.tgz", + "integrity": "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2", + "istextorbinary": "^9.5.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/types": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/types/-/types-10.2.2.tgz", + "integrity": "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@textlint/ast-node-types": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.7.1.tgz", + "integrity": "sha512-Wii5UgUKFEh9Uv6wbq1zr4/Kf+dtjiUuzPrrXzKp8H+ifkvKNzi23V4Nz+6wVyHQn5T28AFuc8VH8OtzvGYecA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@textlint/linter-formatter/-/linter-formatter-15.7.1.tgz", + "integrity": "sha512-TdwZ/debWYFD05K3CcoHtwvnCrza29wZxD+BjDTk/V5N7iRqkK1dTTHSD4A8AIgROLiDkHJmIKQbasbmsg8AvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azu/format-text": "^1.0.2", + "@azu/style-format": "^1.0.1", + "@textlint/module-interop": "15.7.1", + "@textlint/resolver": "15.7.1", + "@textlint/types": "15.7.1", + "chalk": "^4.1.2", + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "lodash": "^4.18.1", + "pluralize": "^2.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "table": "^6.9.0", + "text-table": "^0.2.0" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/pluralize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-2.0.0.tgz", + "integrity": "sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/module-interop": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@textlint/module-interop/-/module-interop-15.7.1.tgz", + "integrity": "sha512-Jg+sQW2L/cRJypk59wtcMUVVpt8vmit5ZMT3gUnFwevP3A6Qp1HfOtUy9ObT4hBX3lOSGT/ekcCDxR1pL7uH1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/resolver": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@textlint/resolver/-/resolver-15.7.1.tgz", + "integrity": "sha512-8XnO0pgF6mXnm41VvWmBbEIdGPhiCUt31uLZkOis1ECeg/1SoUcIT6Mx/F0e1rukq8l0UlOSeY9a31CsvRMK0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/types": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@textlint/types/-/types-15.7.1.tgz", + "integrity": "sha512-Vye/GmFNBTgVzZFtIFJTmLB+s2A7oIADxNG6r9UhfPuY+Czv0z5G3xeyFZZudPlfxURsKUyPIU5XsjOFqVp33A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@textlint/ast-node-types": "15.7.1" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.20.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz", + "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sarif": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.7.tgz", + "integrity": "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/vscode": { + "version": "1.125.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.125.0.tgz", + "integrity": "sha512-0icm/ZQAaism87P0ekHqi4/Ju9du+Tm0RUW+y7vqRsxY2cY0FNRX1nAnaW7nT6npPt2tfHiheZ55Zm9UhqonFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.6.tgz", + "integrity": "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", + "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.9", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vscode/vsce": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.9.2.tgz", + "integrity": "sha512-XSxMosEEDO6vLxELAHVkwmhC0qe0ijZni2jB9Rcs8kQsW4lhTDQ/wMzmwFs/buotAWSnpmUp/dRWD2ufG3UYKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@secretlint/node": "^10.1.2", + "@secretlint/secretlint-formatter-sarif": "^10.1.2", + "@secretlint/secretlint-rule-no-dotenv": "^10.1.2", + "@secretlint/secretlint-rule-preset-recommend": "^10.1.2", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^12.1.0", + "form-data": "^4.0.0", + "glob": "^13.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^14.1.0", + "mime": "^1.3.4", + "minimatch": "^10.2.2", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "secretlint": "^10.1.2", + "semver": "^7.5.2", + "tmp": "^0.2.3", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^3.2.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", + "integrity": "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.6", + "@vscode/vsce-sign-alpine-x64": "2.0.6", + "@vscode/vsce-sign-darwin-arm64": "2.0.6", + "@vscode/vsce-sign-darwin-x64": "2.0.6", + "@vscode/vsce-sign-linux-arm": "2.0.6", + "@vscode/vsce-sign-linux-arm64": "2.0.6", + "@vscode/vsce-sign-linux-x64": "2.0.6", + "@vscode/vsce-sign-win32-arm64": "2.0.6", + "@vscode/vsce-sign-win32-x64": "2.0.6" + } + }, + "node_modules/@vscode/vsce-sign-alpine-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", + "integrity": "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-alpine-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", + "integrity": "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", + "integrity": "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", + "integrity": "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", + "integrity": "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", + "integrity": "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-win32-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", + "integrity": "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", + "integrity": "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/boundary": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", + "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "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, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "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==", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "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.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "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==", + "dev": true, + "license": "BSD-2-Clause", + "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/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "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", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.0.tgz", + "integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz", + "integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.2.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hono": { + "version": "4.12.26", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.26.tgz", + "integrity": "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw==", + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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-it-type": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/is-it-type/-/is-it-type-5.1.3.tgz", + "integrity": "sha512-AX2uU0HW+TxagTgQXOJY7+2fbFHemC7YFBwN1XqD8qQMKdtfbOC8OC3fUb4s5NU59a3662Dzwto8tWDdZYRXxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "globalthis": "^1.0.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "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", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jose": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", + "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json-schema-typed": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "license": "BSD-2-Clause" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/markdown-it": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.1", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "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/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/nanoid": { + "version": "3.3.14", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.14.tgz", + "integrity": "sha512-U9kYi5bpVMEI31yC8iw4bJJp0avcHXA0W8/wNfLfnvJYzihQo2ZRPYPvpAAd570HAcCBjCTN7vnr+v4StKl1IQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-sarif-builder": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", + "integrity": "sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ovsx": { + "version": "0.10.12", + "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.10.12.tgz", + "integrity": "sha512-WwMj1iQDvCk02029oxPnkFXsPrHZ+WzmoNW5pJ8JGepHtL30i2JE4s3C3wqzQqj6a35vx2hp0gV3TdfefGmvMg==", + "dev": true, + "license": "EPL-2.0", + "dependencies": { + "@vscode/vsce": "^3.7.1", + "commander": "^6.2.1", + "follow-redirects": "^1.16.0", + "is-ci": "^2.0.0", + "leven": "^3.1.0", + "semver": "^7.6.0", + "tmp": "^0.2.3", + "yauzl-promise": "^4.0.0" + }, + "bin": { + "ovsx": "bin/ovsx" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/ovsx/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc-config-loader": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.4.tgz", + "integrity": "sha512-3GiwEzklkbXTDp52UR5nT8iXgYAx1V9ZG/kDZT7p60u2GCv2XTwQq4NzinMoMpNtXhmt3WkhYXcj6HH8HdwCEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "json5": "^2.2.3", + "require-from-string": "^2.0.2" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/secretlint": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", + "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, + "bin": { + "secretlint": "bin/secretlint.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-invariant": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/simple-invariant/-/simple-invariant-2.0.1.tgz", + "integrity": "sha512-1sbhsxqI+I2tqlmjbz99GXNmZtr6tKIyEgGGnJw/MKGblalqk/XoOYYFJlBzTKZCxx8kLaD3FD5s9BEEjx5Pyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terminal-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", + "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "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, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "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/type-is": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "license": "MIT", + "dependencies": { + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vitest": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.9", + "@vitest/mocker": "2.1.9", + "@vitest/pretty-format": "^2.1.9", + "@vitest/runner": "2.1.9", + "@vitest/snapshot": "2.1.9", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.9", + "@vitest/ui": "2.1.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", + "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yauzl-promise/-/yauzl-promise-4.0.0.tgz", + "integrity": "sha512-/HCXpyHXJQQHvFq9noqrjfa/WpQC2XYs3vI7tBiAi4QiIU1knvYhZGaO1QPjwIVMdqflxbmwgMXtYeaRiAE0CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@node-rs/crc32": "^1.7.0", + "is-it-type": "^5.1.2", + "simple-invariant": "^2.0.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f9ff212 --- /dev/null +++ b/package.json @@ -0,0 +1,92 @@ +{ + "name": "agentage-memory", + "displayName": "Agentage Memory", + "description": "Connect VS Code to your Agentage Memory in the cloud and search it over MCP.", + "version": "0.0.1", + "publisher": "agentage", + "license": "MIT", + "icon": "media/icon.png", + "engines": { + "vscode": "^1.85.0" + }, + "categories": [ + "Other" + ], + "keywords": [ + "mcp", + "memory", + "search", + "ai", + "oauth", + "knowledge-base", + "notes", + "agentage" + ], + "galleryBanner": { + "color": "#f3a52b", + "theme": "dark" + }, + "pricing": "Free", + "qna": false, + "homepage": "https://memory.agentage.io", + "repository": { + "type": "git", + "url": "https://github.com/agentage/vscode-memory.git" + }, + "bugs": { + "url": "https://github.com/agentage/vscode-memory/issues" + }, + "capabilities": { + "untrustedWorkspaces": { + "supported": true + }, + "virtualWorkspaces": true + }, + "extensionKind": [ + "ui", + "workspace" + ], + "main": "./dist/extension.js", + "activationEvents": [], + "contributes": { + "commands": [ + { + "command": "agentage.searchMemory", + "title": "Search Memory", + "category": "Agentage" + } + ], + "configuration": { + "title": "Agentage Memory", + "properties": { + "agentage.mcpUrl": { + "type": "string", + "default": "https://memory.agentage.io/mcp", + "markdownDescription": "Agentage Memory MCP endpoint (Streamable HTTP). Point at a different stack (e.g. dev) here.", + "order": 0 + } + } + } + }, + "scripts": { + "vscode:prepublish": "npm run package", + "compile": "node esbuild.js", + "watch": "node esbuild.js --watch", + "package": "node esbuild.js --production", + "check-types": "tsc --noEmit", + "test": "vitest run", + "test:watch": "vitest" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.29.0" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "@types/vscode": "^1.85.0", + "@vscode/vsce": "^3.9.2", + "esbuild": "^0.24.0", + "ovsx": "^0.10.11", + "typescript": "^5.7.0", + "vitest": "^2.1.0" + } +} diff --git a/src/auth.ts b/src/auth.ts new file mode 100644 index 0000000..e829250 --- /dev/null +++ b/src/auth.ts @@ -0,0 +1,148 @@ +import * as vscode from 'vscode'; +import * as http from 'node:http'; +import type { AddressInfo } from 'node:net'; +import type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js'; +import type { + OAuthClientInformationFull, + OAuthClientMetadata, + OAuthTokens, +} from '@modelcontextprotocol/sdk/shared/auth.js'; +import { CLIENT_NAME, SCOPE } from './config'; + +const KEY_CLIENT = 'agentage.clientInformation'; +const KEY_TOKENS = 'agentage.tokens'; +const KEY_VERIFIER = 'agentage.codeVerifier'; + +type CallbackServer = { + server: http.Server; + port: number; + code: Promise; +}; + +function startLoopbackServer(): Promise { + return new Promise((resolve, reject) => { + let resolveCode!: (code: string) => void; + let rejectCode!: (err: Error) => void; + const code = new Promise((res, rej) => { + resolveCode = res; + rejectCode = rej; + }); + + const server = http.createServer((req, res) => { + const url = new URL(req.url ?? '/', 'http://127.0.0.1'); + if (url.pathname !== '/callback') { + res.writeHead(404); + res.end(); + return; + } + const authCode = url.searchParams.get('code'); + const error = url.searchParams.get('error'); + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end( + '' + + '

agentage Memory

Signed in. You can close this tab and return to your editor.

' + ); + if (error) rejectCode(new Error(`Authorization failed: ${error}`)); + else if (authCode) resolveCode(authCode); + else rejectCode(new Error('No authorization code in callback')); + }); + + server.on('error', reject); + server.listen(0, '127.0.0.1', () => { + const port = (server.address() as AddressInfo).port; + resolve({ server, port, code }); + }); + }); +} + +/** + * OAuth 2.1 + PKCE + DCR provider for the MCP SDK, backed by VS Code SecretStorage. + * The SDK drives DCR, PKCE and the token exchange; we only persist + open the browser + * and capture the loopback redirect. + */ +export class VsCodeOAuthProvider implements OAuthClientProvider { + private callback?: CallbackServer; + private _redirectUrl = 'http://127.0.0.1:0/callback'; + + constructor(private readonly secrets: vscode.SecretStorage) {} + + get redirectUrl(): string { + return this._redirectUrl; + } + + get clientMetadata(): OAuthClientMetadata { + return { + client_name: CLIENT_NAME, + redirect_uris: [this._redirectUrl], + grant_types: ['authorization_code', 'refresh_token'], + response_types: ['code'], + token_endpoint_auth_method: 'none', + scope: SCOPE, + }; + } + + async clientInformation(): Promise { + const raw = await this.secrets.get(KEY_CLIENT); + return raw ? (JSON.parse(raw) as OAuthClientInformationFull) : undefined; + } + + async saveClientInformation(info: OAuthClientInformationFull): Promise { + await this.secrets.store(KEY_CLIENT, JSON.stringify(info)); + } + + async tokens(): Promise { + const raw = await this.secrets.get(KEY_TOKENS); + return raw ? (JSON.parse(raw) as OAuthTokens) : undefined; + } + + async saveTokens(tokens: OAuthTokens): Promise { + await this.secrets.store(KEY_TOKENS, JSON.stringify(tokens)); + } + + async saveCodeVerifier(verifier: string): Promise { + await this.secrets.store(KEY_VERIFIER, verifier); + } + + async codeVerifier(): Promise { + const v = await this.secrets.get(KEY_VERIFIER); + if (!v) throw new Error('Missing PKCE code verifier'); + return v; + } + + async redirectToAuthorization(authorizationUrl: URL): Promise { + vscode.window.setStatusBarMessage( + `Agentage Memory: opening ${authorizationUrl.host} to sign in...`, + 6000 + ); + await vscode.env.openExternal(vscode.Uri.parse(authorizationUrl.toString())); + } + + async invalidateCredentials( + scope: 'all' | 'client' | 'tokens' | 'verifier' + ): Promise { + if (scope === 'all' || scope === 'client') await this.secrets.delete(KEY_CLIENT); + if (scope === 'all' || scope === 'tokens') await this.secrets.delete(KEY_TOKENS); + if (scope === 'all' || scope === 'verifier') await this.secrets.delete(KEY_VERIFIER); + } + + // --- loopback lifecycle, used by the client around an interactive connect --- + + async startCallback(): Promise { + this.callback = await startLoopbackServer(); + this._redirectUrl = `http://127.0.0.1:${this.callback.port}/callback`; + } + + waitForCode(): Promise { + if (!this.callback) throw new Error('Callback server not started'); + return this.callback.code; + } + + stopCallback(): void { + this.callback?.server.close(); + this.callback = undefined; + } + + async signOut(): Promise { + await this.invalidateCredentials('all'); + } +} diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..bbc0d1a --- /dev/null +++ b/src/config.ts @@ -0,0 +1,14 @@ +import * as vscode from 'vscode'; + +export const SCHEME = 'agentage-memory'; +export const CLIENT_NAME = 'agentage Memory (VS Code)'; + +// Read-only search needs only memory:read; offline_access keeps the refresh token. +export const SCOPE = 'memory:read offline_access'; + +export function getMcpUrl(): string { + const configured = vscode.workspace + .getConfiguration('agentage') + .get('mcpUrl'); + return (configured && configured.trim()) || 'https://memory.agentage.io/mcp'; +} diff --git a/src/doc-provider.ts b/src/doc-provider.ts new file mode 100644 index 0000000..0e656bd --- /dev/null +++ b/src/doc-provider.ts @@ -0,0 +1,17 @@ +import * as vscode from 'vscode'; +import type { MemoryClient } from './mcp-client'; + +/** Serves memory bodies on the agentage-memory:// scheme. These docs are read-only. */ +export class MemoryDocProvider implements vscode.TextDocumentContentProvider { + constructor(private readonly memory: MemoryClient) {} + + async provideTextDocumentContent(uri: vscode.Uri): Promise { + const path = uri.path.replace(/^\/+/, ''); + try { + return await this.memory.read(path); + } catch (e) { + const message = e instanceof Error ? e.message : String(e); + return `> agentage Memory: failed to load \`${path}\`\n>\n> ${message}`; + } + } +} diff --git a/src/extension.ts b/src/extension.ts new file mode 100644 index 0000000..a699ac1 --- /dev/null +++ b/src/extension.ts @@ -0,0 +1,31 @@ +import * as vscode from 'vscode'; +import { VsCodeOAuthProvider } from './auth'; +import { MemoryClient } from './mcp-client'; +import { MemoryDocProvider } from './doc-provider'; +import { runSearch } from './search'; +import { SCHEME } from './config'; + +export function activate(context: vscode.ExtensionContext): void { + const auth = new VsCodeOAuthProvider(context.secrets); + const memory = new MemoryClient(auth); + + const signOut = async () => { + await memory.disconnect(); + await auth.signOut(); + vscode.window.showInformationMessage('Agentage Memory: signed out.'); + }; + + context.subscriptions.push( + vscode.workspace.registerTextDocumentContentProvider( + SCHEME, + new MemoryDocProvider(memory) + ), + vscode.commands.registerCommand('agentage.searchMemory', () => + runSearch(memory, signOut) + ) + ); +} + +export function deactivate(): void { + // nothing to tear down: the MCP client is stateless HTTP +} diff --git a/src/mcp-client.ts b/src/mcp-client.ts new file mode 100644 index 0000000..39f77ae --- /dev/null +++ b/src/mcp-client.ts @@ -0,0 +1,108 @@ +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; +import { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js'; +import type { VsCodeOAuthProvider } from './auth'; +import { getMcpUrl } from './config'; +import { + extractBody, + mapSearchResults, + type MemoryHit, +} from './search-core'; + +type ToolResult = { + content?: Array<{ type: string; text?: string }>; + structuredContent?: unknown; +}; + +function textOf(result: ToolResult): string { + return (result.content ?? []) + .filter((c) => c.type === 'text' && typeof c.text === 'string') + .map((c) => c.text as string) + .join('\n'); +} + +function jsonOf(result: ToolResult): unknown { + if (result.structuredContent !== undefined) return result.structuredContent; + try { + return JSON.parse(textOf(result)); + } catch { + return {}; + } +} + +/** Lazily-connected MCP client for memory.agentage.io/mcp. Connects (with OAuth) once. */ +export class MemoryClient { + private client?: Client; + private connecting?: Promise; + + constructor(private readonly auth: VsCodeOAuthProvider) {} + + private async connect(): Promise { + if (this.client) return this.client; + if (this.connecting) return this.connecting; + this.connecting = this.doConnect(); + try { + return await this.connecting; + } finally { + this.connecting = undefined; + } + } + + private async doConnect(): Promise { + const url = new URL(getMcpUrl()); + await this.auth.startCallback(); + const client = new Client( + { name: 'agentage-vscode', version: '0.0.1' }, + { capabilities: {} } + ); + try { + const transport = new StreamableHTTPClientTransport(url, { + authProvider: this.auth, + }); + try { + await client.connect(transport); + } catch (e) { + if (!(e instanceof UnauthorizedError)) throw e; + // First run: browser is opening; capture the loopback redirect, exchange, reconnect. + const code = await this.auth.waitForCode(); + await transport.finishAuth(code); + const authed = new StreamableHTTPClientTransport(url, { + authProvider: this.auth, + }); + await client.connect(authed); + } + } finally { + this.auth.stopCallback(); + } + this.client = client; + return client; + } + + async search(query: string, limit = 20, signal?: AbortSignal): Promise { + const client = await this.connect(); + const result = (await client.callTool( + { name: 'memory__search', arguments: { query, limit } }, + undefined, + { signal } + )) as ToolResult; + return mapSearchResults(jsonOf(result)); + } + + async read(path: string): Promise { + const client = await this.connect(); + const result = (await client.callTool({ + name: 'memory__read', + arguments: { path }, + })) as ToolResult; + return extractBody(jsonOf(result), textOf(result)); + } + + async disconnect(): Promise { + try { + await this.client?.close(); + } catch { + // ignore + } + this.client = undefined; + } +} diff --git a/src/search-core.ts b/src/search-core.ts new file mode 100644 index 0000000..d5adc60 --- /dev/null +++ b/src/search-core.ts @@ -0,0 +1,49 @@ +// Pure helpers - no 'vscode' import, so they are unit-testable with vitest. + +export interface MemoryHit { + path: string; + title: string; + snippet: string; + score?: number; + updated?: string; +} + +export interface QuickItem { + label: string; + description: string; + detail?: string; +} + +/** Normalize a memory__search result (structuredContent or parsed JSON) into hits. */ +export function mapSearchResults(data: unknown): MemoryHit[] { + const results = (data as { results?: unknown })?.results; + if (!Array.isArray(results)) return []; + return results + .map((r): MemoryHit => { + const row = r as Record; + const path = String(row.path ?? ''); + return { + path, + title: String(row.title ?? row.path ?? 'Untitled'), + snippet: String(row.snippet ?? ''), + score: typeof row.score === 'number' ? row.score : undefined, + updated: typeof row.updated === 'string' ? row.updated : undefined, + }; + }) + .filter((h) => h.path.length > 0); +} + +/** A hit becomes a QuickPick row: title + path + matched snippet. */ +export function hitToQuickItem(hit: MemoryHit): QuickItem { + return { + label: hit.title, + description: hit.path, + detail: hit.snippet || undefined, + }; +} + +/** Strip the read-only doc body out of a memory__read tool result. */ +export function extractBody(data: unknown, fallbackText: string): string { + const body = (data as { body?: unknown })?.body; + return typeof body === 'string' ? body : fallbackText; +} diff --git a/src/search.ts b/src/search.ts new file mode 100644 index 0000000..f1a184a --- /dev/null +++ b/src/search.ts @@ -0,0 +1,95 @@ +import * as vscode from 'vscode'; +import type { MemoryClient } from './mcp-client'; +import { hitToQuickItem } from './search-core'; +import { SCHEME } from './config'; + +const DEBOUNCE_MS = 250; + +const settingsButton: vscode.QuickInputButton = { + iconPath: new vscode.ThemeIcon('gear'), + tooltip: 'Agentage Memory settings', +}; + +const signOutButton: vscode.QuickInputButton = { + iconPath: new vscode.ThemeIcon('sign-out'), + tooltip: 'Sign out of Agentage Memory', +}; + +/** The one feature: live search-as-you-type, open the hit read-only on accept. */ +export function runSearch(memory: MemoryClient, signOut: () => Thenable): void { + const qp = vscode.window.createQuickPick(); + qp.placeholder = 'Search your memory...'; + qp.buttons = [settingsButton, signOutButton]; + // memory__search is substring, so the snippet contains the query -> matchOnDetail + // keeps server hits visible past VS Code's own input filter. + qp.matchOnDescription = true; + qp.matchOnDetail = true; + + let timer: ReturnType | undefined; + let inflight: AbortController | undefined; + + const search = (value: string) => { + if (timer) clearTimeout(timer); + timer = setTimeout(async () => { + const query = value.trim(); + if (!query) { + qp.items = []; + return; + } + inflight?.abort(); + const controller = new AbortController(); + inflight = controller; + qp.busy = true; + try { + const hits = await memory.search(query, 20, controller.signal); + if (controller.signal.aborted) return; + qp.items = hits.map(hitToQuickItem); + } catch (e) { + if (controller.signal.aborted) return; + qp.items = []; + const message = e instanceof Error ? e.message : String(e); + vscode.window.setStatusBarMessage(`agentage Memory: ${message}`, 4000); + } finally { + if (!controller.signal.aborted) qp.busy = false; + } + }, DEBOUNCE_MS); + }; + + qp.onDidChangeValue(search); + + qp.onDidTriggerButton(async (button) => { + if (button === settingsButton) { + qp.hide(); + await vscode.commands.executeCommand( + 'workbench.action.openSettings', + '@ext:agentage.agentage-memory' + ); + } else if (button === signOutButton) { + qp.hide(); + await signOut(); + } + }); + + qp.onDidAccept(async () => { + const path = qp.selectedItems[0]?.description; + qp.hide(); + if (!path) return; + const uri = vscode.Uri.from({ scheme: SCHEME, path: `/${path}` }); + try { + const doc = await vscode.workspace.openTextDocument(uri); + await vscode.languages.setTextDocumentLanguage(doc, 'markdown'); + await vscode.window.showTextDocument(doc, { preview: true }); + } catch (e) { + const message = e instanceof Error ? e.message : String(e); + vscode.window.showErrorMessage(`agentage Memory: could not open ${path}: ${message}`); + } + }); + + qp.onDidHide(() => { + inflight?.abort(); + if (timer) clearTimeout(timer); + qp.dispose(); + }); + + qp.show(); +} diff --git a/test/search-core.test.ts b/test/search-core.test.ts new file mode 100644 index 0000000..1ab3fa1 --- /dev/null +++ b/test/search-core.test.ts @@ -0,0 +1,78 @@ +import { describe, it, expect } from 'vitest'; +import { + mapSearchResults, + hitToQuickItem, + extractBody, +} from '../src/search-core'; + +describe('mapSearchResults', () => { + it('maps a structured results array into hits', () => { + const hits = mapSearchResults({ + results: [ + { + path: 'work/tasks/plan.md', + title: 'Plan', + snippet: '...the plan is...', + score: 3, + updated: '2026-06-20', + }, + ], + }); + expect(hits).toEqual([ + { + path: 'work/tasks/plan.md', + title: 'Plan', + snippet: '...the plan is...', + score: 3, + updated: '2026-06-20', + }, + ]); + }); + + it('falls back to path as title when title is missing', () => { + const [hit] = mapSearchResults({ results: [{ path: 'a/b.md' }] }); + expect(hit.title).toBe('a/b.md'); + expect(hit.snippet).toBe(''); + }); + + it('drops entries without a path', () => { + const hits = mapSearchResults({ + results: [{ title: 'no path' }, { path: 'ok.md' }], + }); + expect(hits).toHaveLength(1); + expect(hits[0].path).toBe('ok.md'); + }); + + it('returns [] for missing or malformed input', () => { + expect(mapSearchResults(undefined)).toEqual([]); + expect(mapSearchResults({})).toEqual([]); + expect(mapSearchResults({ results: 'nope' })).toEqual([]); + }); +}); + +describe('hitToQuickItem', () => { + it('uses title as label and path as description', () => { + const item = hitToQuickItem({ + path: 'notes/x.md', + title: 'X', + snippet: 'hello', + }); + expect(item).toEqual({ label: 'X', description: 'notes/x.md', detail: 'hello' }); + }); + + it('omits empty detail', () => { + const item = hitToQuickItem({ path: 'x.md', title: 'X', snippet: '' }); + expect(item.detail).toBeUndefined(); + }); +}); + +describe('extractBody', () => { + it('prefers structured body', () => { + expect(extractBody({ body: 'hi' }, 'fallback')).toBe('hi'); + }); + + it('falls back to text when body is absent', () => { + expect(extractBody({}, 'fallback')).toBe('fallback'); + expect(extractBody(undefined, 'fallback')).toBe('fallback'); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5fdd7f4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "ESNext", + "target": "ES2022", + "lib": ["ES2022"], + "moduleResolution": "Bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "noEmit": true, + "sourceMap": true, + "rootDir": ".", + "types": ["node", "vscode"] + }, + "include": ["src/**/*.ts", "test/**/*.ts"] +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..fa69665 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['test/**/*.test.ts'], + environment: 'node', + }, +}); From 837c5df72db55b51a3f71e4a7e1eae3766288459 Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 01:38:25 +0200 Subject: [PATCH 02/11] docs: add demo.gif of the search flow + wire into README --- .vscodeignore | 2 + README.md | 2 +- media/demo.gif | Bin 0 -> 56398 bytes scripts/build-demo.mjs | 280 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 media/demo.gif create mode 100644 scripts/build-demo.mjs diff --git a/.vscodeignore b/.vscodeignore index 7e9f0df..cf45adf 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -9,6 +9,8 @@ vitest.config.* **/*.ts **/*.map media/*.svg +media/demo.gif +scripts/** .gitignore .github/** CONTRIBUTING.md diff --git a/README.md b/README.md index 6e6bac8..10e53ed 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Installs](https://img.shields.io/visual-studio-marketplace/i/agentage.agentage-memory?label=installs)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage-memory) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) - +![Agentage: Search Memory in VS Code](https://github.com/agentage/vscode-memory/raw/master/media/demo.gif) This extension connects your editor to your **cloud memory over MCP** - the hosted Agentage Memory endpoint at `memory.agentage.io/mcp`, the same memory every AI you use already reads and writes. One sign-in, then search it from the command palette. No local copy, no API keys. diff --git a/media/demo.gif b/media/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..307a776b969ecd525fc73c15eb41121ccba259a7 GIT binary patch literal 56398 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 literal 0 HcmV?d00001 diff --git a/scripts/build-demo.mjs b/scripts/build-demo.mjs new file mode 100644 index 0000000..a20e1aa --- /dev/null +++ b/scripts/build-demo.mjs @@ -0,0 +1,280 @@ +// Builds media/demo.gif - a mockup of the Agentage: Search Memory flow. +// SVG frames -> PNG (rsvg-convert) -> animated GIF (ImageMagick convert). +// Run: node scripts/build-demo.mjs +import { execSync } from 'node:child_process'; +import { mkdirSync, writeFileSync, rmSync } from 'node:fs'; + +const W = 1000; +const H = 620; +const GOLD = '#f3a52b'; +const TMP = '/tmp/agentage-demo'; +const OUT = 'media/demo.gif'; + +const esc = (s) => + s.replace(/&/g, '&').replace(//g, '>'); + +// text with the matched term highlighted gold +function snippet(text, term, x, y, size, color) { + const i = text.toLowerCase().indexOf(term.toLowerCase()); + if (i < 0) + return `${esc(text)}`; + const a = esc(text.slice(0, i)); + const b = esc(text.slice(i, i + term.length)); + const c = esc(text.slice(i + term.length)); + return `${a}${b}${c}`; +} + +const gearIcon = (cx, cy) => { + const teeth = Array.from({ length: 8 }, (_, k) => { + const ang = (k * Math.PI) / 4; + const x1 = cx + Math.cos(ang) * 5.2; + const y1 = cy + Math.sin(ang) * 5.2; + const x2 = cx + Math.cos(ang) * 7.6; + const y2 = cy + Math.sin(ang) * 7.6; + return ``; + }).join(''); + return `${teeth}`; +}; + +const signOutIcon = (cx, cy) => + ` + + + + `; + +function chrome(tabLabel, readOnly) { + const ro = readOnly + ? ` + + + + Read-only + ` + : ''; + return ` + + + + Agentage Memory - Visual Studio Code + + + + + + + + + ${esc(tabLabel)} + ${ro}`; +} +const tabW = (label) => Math.round(28 + label.length * 7.2); + +function dim() { + return ``; +} + +// quick-input palette +function palette({ input, placeholder, cursor, buttons, list, busy }) { + const px = 214; + const pw = 640; + const py = 44; + const rowH = 38; + let svg = ``; + svg += ``; + // input box + svg += ``; + const tx = px + 18; + const ty = py + 8 + (rowH - 8) / 2 + 4.5; + if (input) { + svg += `${esc(input)}`; + if (cursor) { + const cw = 18 + input.length * 7.7; + svg += ``; + } + } else if (placeholder) { + svg += `Search your memory...`; + if (cursor) svg += ``; + } + // buttons on the right + if (buttons) { + svg += gearIcon(px + pw - 46, py + 8 + (rowH - 8) / 2); + svg += signOutIcon(px + pw - 24, py + 8 + (rowH - 8) / 2); + } + if (busy) { + svg += ``; + svg += ``; + } + // list rows + if (list) { + list.forEach((r, idx) => { + const ry = py + rowH + 6 + idx * 52; + if (r.selected) { + svg += ``; + svg += ``; + } + // title + path + svg += `${esc( + r.title + )}`; + svg += `${esc( + r.path + )}`; + // snippet + svg += snippet(r.snippet, 'auth', px + 18, ry + 39, 11.5, '#9aa0a6'); + }); + } + return svg; +} + +function command() { + const px = 214; + const pw = 640; + const py = 44; + const rowH = 38; + const cmds = [ + { t: 'Agentage: Search Memory', sel: true }, + { t: 'Preferences: Open Settings (UI)', sel: false }, + { t: 'Developer: Reload Window', sel: false }, + ]; + let svg = ``; + svg += ``; + svg += ``; + svg += `> Agentage: Search Mem`; + const cw = 18 + '> Agentage: Search Mem'.length * 7.7; + svg += ``; + cmds.forEach((c, idx) => { + const ry = py + rowH + 6 + idx * 34; + if (c.sel) { + svg += ``; + svg += ``; + } + const idx2 = c.t.toLowerCase().indexOf('search mem'); + if (idx2 >= 0 && c.sel) { + const a = esc(c.t.slice(0, idx2)); + const b = esc(c.t.slice(idx2, idx2 + 'Search Mem'.length)); + const cc = esc(c.t.slice(idx2 + 'Search Mem'.length)); + svg += `${a}${b}${cc}`; + } else { + svg += `${esc( + c.t + )}`; + } + }); + return svg; +} + +function doc() { + const lines = [ + ['# OAuth setup notes', '#569cd6'], + ['', ''], + ['The Memory MCP endpoint signs you in with OAuth 2.1 + PKCE', '#d4d4d4'], + ['and Dynamic Client Registration against auth.agentage.io.', '#d4d4d4'], + ['', ''], + ['- Token lives in the OS keychain (SecretStorage), never on disk.', '#d4d4d4'], + ['- The redirect returns to a local loopback port.', '#d4d4d4'], + ['- Read-only: search and open, no writes.', '#d4d4d4'], + ]; + let svg = ''; + let n = 1; + lines.forEach((ln, i) => { + const y = 96 + i * 26; + svg += `${n}`; + if (ln[0]) + svg += `${esc( + ln[0] + )}`; + n++; + }); + return svg; +} + +const R = [ + { + title: 'Auth service - key decisions', + path: 'work/auth/decisions.md', + snippet: '...a dedicated Better Auth service as the IdP + OAuth 2.1 AS...', + }, + { + title: 'OAuth setup notes', + path: 'notes/oauth-setup.md', + snippet: '...one-click auth: OAuth 2.1 + PKCE + DCR against auth.agentage.io...', + }, + { + title: 'MCP connector soft-launch', + path: 'tasks/mcp-connector.md', + snippet: '...connector + auth path verified live; magic-link onboarding...', + }, +]; + +const frames = [ + { delay: 140, build: () => chrome('search.md', false) + dim() + command() }, + { + delay: 70, + build: () => + chrome('search.md', false) + + dim() + + palette({ placeholder: true, cursor: true, buttons: true }), + }, + { + delay: 55, + build: () => + chrome('search.md', false) + + dim() + + palette({ input: 'auth', cursor: true, buttons: true, busy: true }), + }, + { + delay: 165, + build: () => + chrome('search.md', false) + + dim() + + palette({ + input: 'auth', + buttons: true, + list: R.map((r, i) => ({ ...r, selected: i === 0 })), + }), + }, + { + delay: 95, + build: () => + chrome('search.md', false) + + dim() + + palette({ + input: 'auth', + buttons: true, + list: R.map((r, i) => ({ ...r, selected: i === 1 })), + }), + }, + { delay: 250, build: () => chrome('oauth-setup.md', true) + doc() }, +]; + +rmSync(TMP, { recursive: true, force: true }); +mkdirSync(TMP, { recursive: true }); +const svgWrap = (inner) => + `${inner}`; + +const args = []; +frames.forEach((f, i) => { + const svgPath = `${TMP}/f${i}.svg`; + const pngPath = `${TMP}/f${i}.png`; + writeFileSync(svgPath, svgWrap(f.build())); + execSync(`rsvg-convert -w ${W} -h ${H} "${svgPath}" -o "${pngPath}"`); + args.push(`-delay ${f.delay} "${pngPath}"`); +}); + +mkdirSync('media', { recursive: true }); +execSync( + `convert -loop 0 ${args.join(' ')} -layers optimize "${OUT}"`, + { stdio: 'inherit' } +); +console.log(`wrote ${OUT}`); From 219e597b3bfb75f7a5bfe0b289d2f44e0a06c67f Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 01:44:54 +0200 Subject: [PATCH 03/11] docs: rebuild demo.gif as a Copilot Chat scenario (Q3 milestones from memory) --- README.md | 2 +- media/demo.gif | Bin 56398 -> 30901 bytes scripts/build-demo.mjs | 372 +++++++++++++++-------------------------- 3 files changed, 135 insertions(+), 239 deletions(-) diff --git a/README.md b/README.md index 10e53ed..54d599d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Installs](https://img.shields.io/visual-studio-marketplace/i/agentage.agentage-memory?label=installs)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage-memory) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) -![Agentage: Search Memory in VS Code](https://github.com/agentage/vscode-memory/raw/master/media/demo.gif) +![Copilot Chat answering from your Agentage Memory through the MCP connection](https://github.com/agentage/vscode-memory/raw/master/media/demo.gif) This extension connects your editor to your **cloud memory over MCP** - the hosted Agentage Memory endpoint at `memory.agentage.io/mcp`, the same memory every AI you use already reads and writes. One sign-in, then search it from the command palette. No local copy, no API keys. diff --git a/media/demo.gif b/media/demo.gif index 307a776b969ecd525fc73c15eb41121ccba259a7..ffe25068505269f2ecafe84df73973b02d758375 100644 GIT binary patch literal 30901 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 literal 56398 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 diff --git a/scripts/build-demo.mjs b/scripts/build-demo.mjs index a20e1aa..52db4c6 100644 --- a/scripts/build-demo.mjs +++ b/scripts/build-demo.mjs @@ -1,5 +1,5 @@ -// Builds media/demo.gif - a mockup of the Agentage: Search Memory flow. -// SVG frames -> PNG (rsvg-convert) -> animated GIF (ImageMagick convert). +// Builds media/demo.gif - the agentage memory answering in Copilot Chat +// through the MCP connection. SVG frames -> PNG (rsvg-convert) -> GIF (convert). // Run: node scripts/build-demo.mjs import { execSync } from 'node:child_process'; import { mkdirSync, writeFileSync, rmSync } from 'node:fs'; @@ -9,272 +9,168 @@ const H = 620; const GOLD = '#f3a52b'; const TMP = '/tmp/agentage-demo'; const OUT = 'media/demo.gif'; +const CX = 512; // chat panel left edge +const PAD = 18; +const CL = CX + PAD; // content left +const FS = "font-family=\"'DejaVu Sans',sans-serif\""; +const FM = "font-family=\"'DejaVu Sans Mono',monospace\""; -const esc = (s) => - s.replace(/&/g, '&').replace(//g, '>'); +const esc = (s) => s.replace(/&/g, '&').replace(//g, '>'); +const txt = (x, y, s, fill, str, extra = '') => + `${esc(str)}`; +const mono = (x, y, s, fill, str, extra = '') => + `${esc(str)}`; -// text with the matched term highlighted gold -function snippet(text, term, x, y, size, color) { - const i = text.toLowerCase().indexOf(term.toLowerCase()); - if (i < 0) - return `${esc(text)}`; - const a = esc(text.slice(0, i)); - const b = esc(text.slice(i, i + term.length)); - const c = esc(text.slice(i + term.length)); - return `${a}${b}${c}`; -} +const rocketA = (cx, cy, sc, fill = GOLD) => + ``; -const gearIcon = (cx, cy) => { - const teeth = Array.from({ length: 8 }, (_, k) => { - const ang = (k * Math.PI) / 4; - const x1 = cx + Math.cos(ang) * 5.2; - const y1 = cy + Math.sin(ang) * 5.2; - const x2 = cx + Math.cos(ang) * 7.6; - const y2 = cy + Math.sin(ang) * 7.6; - return ``; - }).join(''); - return `${teeth}`; +const sparkle = (cx, cy, s, fill = GOLD) => { + const p = [ + [cx, cy - s], + [cx + s * 0.26, cy - s * 0.26], + [cx + s, cy], + [cx + s * 0.26, cy + s * 0.26], + [cx, cy + s], + [cx - s * 0.26, cy + s * 0.26], + [cx - s, cy], + [cx - s * 0.26, cy - s * 0.26], + ] + .map((q) => q.map((n) => n.toFixed(1)).join(',')) + .join(' '); + return ``; }; -const signOutIcon = (cx, cy) => - ` - - - - `; - -function chrome(tabLabel, readOnly) { - const ro = readOnly - ? ` - - - - Read-only - ` - : ''; +function chrome() { return ` - Agentage Memory - Visual Studio Code + ${txt(W / 2, 19, 12, '#c8c8c8', 'Agentage Memory - Visual Studio Code', 'text-anchor="middle"')} - - - + ${rocketA(24, 70, 1.0)} - - - - ${esc(tabLabel)} - ${ro}`; -} -const tabW = (label) => Math.round(28 + label.length * 7.2); -function dim() { - return ``; + + + + + ${txt(62, 53, 12.5, '#cdcdcd', 'roadmap.md')} + ${mono(72, 100, 12.5, '#4f7da3', '# Product roadmap')} + ${mono(72, 150, 12.5, '#3f3f3f', '...')} + ${mono(72, 184, 12.5, '#7d6a3a', '## Q3 2026')} + ${mono(72, 218, 12.5, '#3f3f46', '')} + + + + + ${sparkle(CL + 6, 49, 6, '#cfcfcf')} + ${txt(CL + 20, 53, 12, '#cfcfcf', 'CHAT', 'letter-spacing="1"')} + `; } -// quick-input palette -function palette({ input, placeholder, cursor, buttons, list, busy }) { - const px = 214; - const pw = 640; - const py = 44; - const rowH = 38; - let svg = ``; - svg += ``; - // input box - svg += ``; - const tx = px + 18; - const ty = py + 8 + (rowH - 8) / 2 + 4.5; - if (input) { - svg += `${esc(input)}`; - if (cursor) { - const cw = 18 + input.length * 7.7; - svg += ``; - } - } else if (placeholder) { - svg += `Search your memory...`; - if (cursor) svg += ``; - } - // buttons on the right - if (buttons) { - svg += gearIcon(px + pw - 46, py + 8 + (rowH - 8) / 2); - svg += signOutIcon(px + pw - 24, py + 8 + (rowH - 8) / 2); - } - if (busy) { - svg += ``; - svg += ``; +function toolChip(x, y, state) { + const w = 322; + let s = + `` + + rocketA(x + 17, y + 15, 0.62); + s += `agentage · memory__search`; + if (state === 'run') { + s += ``; + s += ``; + } else { + s += ``; + s += `5 hits`; } - // list rows - if (list) { - list.forEach((r, idx) => { - const ry = py + rowH + 6 + idx * 52; - if (r.selected) { - svg += ``; - svg += ``; - } - // title + path - svg += `${esc( - r.title - )}`; - svg += `${esc( - r.path - )}`; - // snippet - svg += snippet(r.snippet, 'auth', px + 18, ry + 39, 11.5, '#9aa0a6'); - }); - } - return svg; + return s; } -function command() { - const px = 214; - const pw = 640; - const py = 44; - const rowH = 38; - const cmds = [ - { t: 'Agentage: Search Memory', sel: true }, - { t: 'Preferences: Open Settings (UI)', sel: false }, - { t: 'Developer: Reload Window', sel: false }, - ]; - let svg = ``; - svg += ``; - svg += ``; - svg += `> Agentage: Search Mem`; - const cw = 18 + '> Agentage: Search Mem'.length * 7.7; - svg += ``; - cmds.forEach((c, idx) => { - const ry = py + rowH + 6 + idx * 34; - if (c.sel) { - svg += ``; - svg += ``; +const BULLETS = [ + ['Better Auth single-host login cutover', 'auth/roadmap.md'], + ['Git-store GA + hourly off-box backup', 'git-store/transition.md'], + ['MCP connector directory listing', 'tasks/mcp-directory.md'], + ['VS Code + Cursor memory search', 'features/vscode.md'], +]; + +function chatBody({ input, sent, chip, bullets, closing, spinner }) { + let s = ''; + let y = 96; + // user message + if (sent) { + s += ``; + s += ``; + s += txt(CL + 26, y + 4, 11.5, '#9a9a9a', 'You'); + y += 26; + s += txt(CL, y, 13.5, '#e7e7e7', 'get me the milestones for Q3 2026'); + y += 34; + // assistant header + s += `` + sparkle(CL + 9, y, 6, GOLD); + s += txt(CL + 26, y + 4, 11.5, '#9a9a9a', 'GitHub Copilot'); + y += 22; + if (spinner) { + s += ``; + s += ``; + s += txt(CL + 22, y + 8, 12.5, '#8a8a8a', 'Searching your memory...'); + y += 24; } - const idx2 = c.t.toLowerCase().indexOf('search mem'); - if (idx2 >= 0 && c.sel) { - const a = esc(c.t.slice(0, idx2)); - const b = esc(c.t.slice(idx2, idx2 + 'Search Mem'.length)); - const cc = esc(c.t.slice(idx2 + 'Search Mem'.length)); - svg += `${a}${b}${cc}`; - } else { - svg += `${esc( - c.t - )}`; + if (chip) { + s += toolChip(CL, y, chip); + y += 44; } - }); - return svg; -} - -function doc() { - const lines = [ - ['# OAuth setup notes', '#569cd6'], - ['', ''], - ['The Memory MCP endpoint signs you in with OAuth 2.1 + PKCE', '#d4d4d4'], - ['and Dynamic Client Registration against auth.agentage.io.', '#d4d4d4'], - ['', ''], - ['- Token lives in the OS keychain (SecretStorage), never on disk.', '#d4d4d4'], - ['- The redirect returns to a local loopback port.', '#d4d4d4'], - ['- Read-only: search and open, no writes.', '#d4d4d4'], - ]; - let svg = ''; - let n = 1; - lines.forEach((ln, i) => { - const y = 96 + i * 26; - svg += `${n}`; - if (ln[0]) - svg += `${esc( - ln[0] - )}`; - n++; - }); - return svg; + if (bullets > 0) { + s += txt(CL, y, 13, '#cccccc', 'Your Q3 2026 milestones, from memory:'); + y += 30; + BULLETS.slice(0, bullets).forEach(([m, ref]) => { + s += ``; + s += txt(CL + 16, y, 13, '#dcdcdc', m); + y += 19; + s += mono(CL + 16, y, 10.5, '#6c6c72', ref); + y += 25; + }); + if (closing) { + y += 4; + s += txt(CL, y, 12.5, '#9a9a9a', 'Want owners and target dates for any of these?'); + } + } + } + // input box + const iy = 564; + s += ``; + if (input) { + s += txt(CL + 12, iy + 22, 12.5, '#e2e2e2', input); + const cw = 12 + input.length * 6.9; + s += ``; + } else { + s += txt(CL + 12, iy + 22, 12.5, '#6f6f6f', 'Ask Copilot...'); + } + // send arrow + const ax = W - PAD - 20; + s += ``; + return s; } -const R = [ - { - title: 'Auth service - key decisions', - path: 'work/auth/decisions.md', - snippet: '...a dedicated Better Auth service as the IdP + OAuth 2.1 AS...', - }, - { - title: 'OAuth setup notes', - path: 'notes/oauth-setup.md', - snippet: '...one-click auth: OAuth 2.1 + PKCE + DCR against auth.agentage.io...', - }, - { - title: 'MCP connector soft-launch', - path: 'tasks/mcp-connector.md', - snippet: '...connector + auth path verified live; magic-link onboarding...', - }, -]; - const frames = [ - { delay: 140, build: () => chrome('search.md', false) + dim() + command() }, - { - delay: 70, - build: () => - chrome('search.md', false) + - dim() + - palette({ placeholder: true, cursor: true, buttons: true }), - }, - { - delay: 55, - build: () => - chrome('search.md', false) + - dim() + - palette({ input: 'auth', cursor: true, buttons: true, busy: true }), - }, - { - delay: 165, - build: () => - chrome('search.md', false) + - dim() + - palette({ - input: 'auth', - buttons: true, - list: R.map((r, i) => ({ ...r, selected: i === 0 })), - }), - }, - { - delay: 95, - build: () => - chrome('search.md', false) + - dim() + - palette({ - input: 'auth', - buttons: true, - list: R.map((r, i) => ({ ...r, selected: i === 1 })), - }), - }, - { delay: 250, build: () => chrome('oauth-setup.md', true) + doc() }, + { delay: 150, build: () => chatBody({ input: 'get me the milestones for Q3 2026' }) }, + { delay: 70, build: () => chatBody({ sent: true, spinner: true }) }, + { delay: 75, build: () => chatBody({ sent: true, chip: 'run' }) }, + { delay: 120, build: () => chatBody({ sent: true, chip: 'done', bullets: 2 }) }, + { delay: 280, build: () => chatBody({ sent: true, chip: 'done', bullets: 4, closing: true }) }, ]; rmSync(TMP, { recursive: true, force: true }); mkdirSync(TMP, { recursive: true }); -const svgWrap = (inner) => - `${inner}`; +const wrap = (inner) => + `${chrome()}${inner}`; const args = []; frames.forEach((f, i) => { - const svgPath = `${TMP}/f${i}.svg`; - const pngPath = `${TMP}/f${i}.png`; - writeFileSync(svgPath, svgWrap(f.build())); - execSync(`rsvg-convert -w ${W} -h ${H} "${svgPath}" -o "${pngPath}"`); - args.push(`-delay ${f.delay} "${pngPath}"`); + const svg = `${TMP}/f${i}.svg`; + const png = `${TMP}/f${i}.png`; + writeFileSync(svg, wrap(f.build())); + execSync(`rsvg-convert -w ${W} -h ${H} "${svg}" -o "${png}"`); + args.push(`-delay ${f.delay} "${png}"`); }); mkdirSync('media', { recursive: true }); -execSync( - `convert -loop 0 ${args.join(' ')} -layers optimize "${OUT}"`, - { stdio: 'inherit' } -); +execSync(`convert -loop 0 ${args.join(' ')} -layers optimize "${OUT}"`, { stdio: 'inherit' }); console.log(`wrote ${OUT}`); From 6d60eb40382267b0b6ada6b38498cca05a49c7de Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 02:15:43 +0200 Subject: [PATCH 04/11] refactor: Agentage extension - connect-only over MCP - Rename to Agentage (displayName + id 'agentage.agentage'); memory is the current scope, room to grow. - Add 'Agentage: Connect Memory to this editor': registers the MCP server with the host editor's AI (VS Code install deeplink; Cursor/Windsurf config files, merged not clobbered). VS Code/Cursor/Windsurf detection via env.uriScheme. - Remove the in-process Search Memory command + its client/auth/doc stack and the @modelcontextprotocol/sdk dependency (host editor handles MCP + OAuth). - Bundle 280KB -> 6.3KB; README/CHANGELOG/CONTRIBUTING rewritten. --- CHANGELOG.md | 11 +- CONTRIBUTING.md | 30 +- README.md | 57 ++- package-lock.json | 847 ++------------------------------------ package.json | 13 +- src/auth.ts | 148 ------- src/config.ts | 7 +- src/connect-core.ts | 111 +++++ src/connect-editor.ts | 73 ++++ src/doc-provider.ts | 17 - src/extension.ts | 25 +- src/mcp-client.ts | 108 ----- src/search-core.ts | 49 --- src/search.ts | 95 ----- test/connect-core.test.ts | 73 ++++ test/search-core.test.ts | 78 ---- 16 files changed, 351 insertions(+), 1391 deletions(-) delete mode 100644 src/auth.ts create mode 100644 src/connect-core.ts create mode 100644 src/connect-editor.ts delete mode 100644 src/doc-provider.ts delete mode 100644 src/mcp-client.ts delete mode 100644 src/search-core.ts delete mode 100644 src/search.ts create mode 100644 test/connect-core.test.ts delete mode 100644 test/search-core.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4432866..3ba0f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,12 @@ # Changelog -All notable changes to the Agentage Memory extension are documented here. The -format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and -this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +All notable changes to the Agentage extension are documented here. The format is +based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project +adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.0.1] - 2026-06-21 ### Added -- `Agentage: Search Memory` - live search-as-you-type over your remote memory, results show title, path, and matched line. -- Open a hit as a read-only Markdown document via the `agentage-memory://` scheme. -- OAuth 2.1 + PKCE + Dynamic Client Registration sign-in; token stored in VS Code SecretStorage. -- Settings (gear) and sign-out buttons inside the search box. +- `Agentage: Connect Memory to this editor` - registers the Agentage MCP server (`memory.agentage.io/mcp`) with your editor's AI so it can read your memory. VS Code uses the install deeplink; Cursor and Windsurf get their config file written (merged, never clobbered). - `agentage.mcpUrl` setting to target a different stack. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f40b30..040369b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,34 +10,40 @@ npm test # vitest unit tests (pure helpers) npm run check-types # tsc --noEmit ``` -Press **F5** in VS Code to launch the Extension Development Host, then run **`Agentage: Search Memory`** from the command palette. +Press **F5** in VS Code to launch the Extension Development Host, then run **`Agentage: Connect Memory to this editor`** from the command palette. -Point at a non-prod stack while testing via the `agentage.mcpUrl` setting. +Point at a non-prod stack via the `agentage.mcpUrl` setting before connecting. ## Architecture -A thin [MCP](https://modelcontextprotocol.io) client over `https://memory.agentage.io/mcp` (Streamable HTTP). It calls two of the six memory tools: `memory__search` and `memory__read`. OAuth 2.1 + PKCE + DCR is handled by the MCP SDK's `OAuthClientProvider`; the loopback redirect is captured on `127.0.0.1` and the token is stored in `SecretStorage`. +The extension registers the remote MCP server (`memory.agentage.io/mcp`) with the +host editor's AI agent - it does not talk to MCP itself, and it has no runtime +dependencies. The host editor runs OAuth 2.1 when its agent first uses the server. ``` -src/extension.ts activate(): one command + read-only doc provider -src/search.ts QuickPick: debounce + cancel-in-flight + sign-out button -src/mcp-client.ts MCP Client + StreamableHTTPClientTransport (connect once) -src/auth.ts OAuthClientProvider backed by SecretStorage + loopback callback -src/doc-provider.ts agentage-memory:// read-only document provider -src/search-core.ts pure helpers (the vitest-tested surface) +src/extension.ts activate(): registers the one command +src/connect-editor.ts host detection + register the server (VS Code deeplink / Cursor + Windsurf config file) +src/connect-core.ts pure helpers (host detect, per-editor JSON, JSONC-safe merge) - vitest-tested +src/config.ts the agentage.mcpUrl setting ``` +Per-editor config shapes differ - VS Code `servers` + `type:http` + `url`, Cursor +`mcpServers` + `url`, Windsurf `mcpServers` + `serverUrl` - so existing config is +read-merged, never overwritten. + ## Package a .vsix ```bash -npx @vscode/vsce package # agentage-memory-.vsix +npx @vscode/vsce package # agentage-.vsix npx @vscode/vsce ls # confirm only dist/, README, LICENSE, CHANGELOG, icon, package.json ship -code --install-extension agentage-memory-.vsix +code --install-extension agentage-.vsix ``` ## Release -Publishing to the VS Code Marketplace and Open VSX is automated by `.github/workflows/publish.yml`, triggered on a `v*` tag. Bump `version`, update `CHANGELOG.md`, dogfood the `.vsix` in VS Code and a fork, then: +Publishing to the VS Code Marketplace and Open VSX is automated by +`.github/workflows/publish.yml`, triggered on a `v*` tag. Bump `version`, update +`CHANGELOG.md`, dogfood the `.vsix` in VS Code and a fork, then: ```bash git tag v && git push --tags diff --git a/README.md b/README.md index 54d599d..94693d3 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,56 @@ -# Agentage Memory +# Agentage -> Connect VS Code to your [Agentage Memory](https://memory.agentage.io) in the cloud, and search it - read-only, over MCP. +> Connect your editor's AI to your [Agentage](https://memory.agentage.io) memory - over MCP. -[![VS Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/agentage.agentage-memory?label=VS%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage-memory) -[![Open VSX Version](https://img.shields.io/open-vsx/v/agentage/agentage-memory?label=Open%20VSX)](https://open-vsx.org/extension/agentage/agentage-memory) -[![Installs](https://img.shields.io/visual-studio-marketplace/i/agentage.agentage-memory?label=installs)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage-memory) +[![VS Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/agentage.agentage?label=VS%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage) +[![Open VSX Version](https://img.shields.io/open-vsx/v/agentage/agentage?label=Open%20VSX)](https://open-vsx.org/extension/agentage/agentage) +[![Installs](https://img.shields.io/visual-studio-marketplace/i/agentage.agentage?label=installs)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) -![Copilot Chat answering from your Agentage Memory through the MCP connection](https://github.com/agentage/vscode-memory/raw/master/media/demo.gif) +![Copilot Chat answering from your Agentage memory through the MCP connection](https://github.com/agentage/vscode-memory/raw/master/media/demo.gif) -This extension connects your editor to your **cloud memory over MCP** - the hosted Agentage Memory endpoint at `memory.agentage.io/mcp`, the same memory every AI you use already reads and writes. One sign-in, then search it from the command palette. No local copy, no API keys. +One command wires your editor's AI - GitHub Copilot, Cursor, or Windsurf - to your Agentage memory at `memory.agentage.io/mcp`. Ask in chat, and the agent reads and answers from the same memory every AI you use shares. No copy-paste, no local export. ## Features -- **Connect to the cloud MCP** - one-click **OAuth 2.1** (PKCE + Dynamic Client Registration) sign-in to `memory.agentage.io/mcp` (Streamable HTTP). The connection is the product; everything below runs on top of it. -- **Search your memory** - `Agentage: Search Memory` runs live search-as-you-type; each hit shows its title, file path, and the matched line. -- **Open read-only** - press Enter to open a hit as a read-only Markdown document. No writes, ever. -- **Point at any stack** - a gear button in the search box (and the `agentage.mcpUrl` setting) lets you target prod, dev, or self-hosted. -- **Sign out** - a button in the search box disconnects and clears the token. +- **One command** - `Agentage: Connect Memory to this editor` registers the Agentage MCP server with your editor's AI. +- **Works where you work** - VS Code (Copilot Agent mode), Cursor, and Windsurf. +- **Your editor handles sign-in** - OAuth 2.1 runs in the host's own MCP flow. The extension stores no tokens and sends no data of its own. ## Requirements -- An Agentage Memory account. The first search opens your browser to sign in. +- An Agentage Memory account. Your editor prompts you to sign in the first time its AI uses the server. +- An MCP-capable AI in your editor: GitHub Copilot (Agent mode) in VS Code, Cursor, or Windsurf Cascade. ## Getting started -1. Run **`Agentage: Search Memory`** from the Command Palette (`Ctrl/Cmd+Shift+P`). -2. The status bar shows the sign-in host and your browser opens - approve the connection to `auth.agentage.io`. -3. Back in the editor, type to search; press **Enter** on a result to open it. -4. Use the **gear** button to open settings, or the **sign-out** button to disconnect. +1. Run **`Agentage: Connect Memory to this editor`** from the Command Palette (`Ctrl/Cmd+Shift+P`). +2. VS Code: confirm the install dialog. Cursor / Windsurf: enable or refresh the server in the MCP panel. +3. Open your AI chat in agent mode and ask something from your memory - sign in when prompted. -## Authentication & privacy +## How it works -- Sign-in is **OAuth 2.1 + PKCE + Dynamic Client Registration** against `auth.agentage.io` (opens your browser; the redirect comes back to a local loopback port). -- Your token is stored in **VS Code SecretStorage** (your OS keychain) - never in settings or logs. -- Only your typed query and the path you open are sent to the MCP endpoint. -- **Read-only. No writes. No telemetry.** +The command registers `memory.agentage.io/mcp` (Streamable HTTP) with your editor's MCP configuration - the VS Code install deeplink, or the Cursor / Windsurf config file (merged, never overwritten). Your editor's agent then connects and runs OAuth 2.1 itself. This extension stores no tokens and sends no data of its own. ## Settings | Setting | Default | Description | | --- | --- | --- | -| `agentage.mcpUrl` | `https://memory.agentage.io/mcp` | The cloud memory MCP endpoint (Streamable HTTP). Point at a different stack here. | +| `agentage.mcpUrl` | `https://memory.agentage.io/mcp` | The MCP endpoint to register. Point at a different stack here. | -## Compatibility +## Commands -VS Code, and forks via [Open VSX](https://open-vsx.org/extension/agentage/agentage-memory): **Cursor, Windsurf, VSCodium**. +| Command | What it does | +| --- | --- | +| `Agentage: Connect Memory to this editor` | Registers the MCP server so your editor's AI can read your memory. | -## Known limitations (v1) +## Compatibility -- Search is literal substring (`git grep`), not semantic. -- Each keystroke is a live network round-trip (debounced, prior request cancelled). -- A single memory is assumed; multi-vault selection lands later. +VS Code (Copilot Agent mode), and via [Open VSX](https://open-vsx.org/extension/agentage/agentage): **Cursor, Windsurf, VSCodium**. -## Links +## Privacy -[Homepage](https://memory.agentage.io) · [Repository](https://github.com/agentage/vscode-memory) · [Issues](https://github.com/agentage/vscode-memory/issues) · [Changelog](./CHANGELOG.md) +The extension only writes the server URL into your editor's MCP config (or opens the install deeplink). It stores no tokens, collects no telemetry, and sends no data of its own. Sign-in and all memory access happen through your editor's own MCP client. ## License diff --git a/package-lock.json b/package-lock.json index f6a208a..5b4c44d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,13 @@ { - "name": "agentage-memory", + "name": "agentage", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "agentage-memory", + "name": "agentage", "version": "0.0.1", "license": "MIT", - "dependencies": { - "@modelcontextprotocol/sdk": "^1.29.0" - }, "devDependencies": { "@types/node": "^22.10.0", "@types/vscode": "^1.85.0", @@ -693,18 +690,6 @@ "node": ">=18" } }, - "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -712,46 +697,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", - "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", - "license": "MIT", - "dependencies": { - "@hono/node-server": "^1.19.9", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.2.1", - "express-rate-limit": "^8.2.1", - "hono": "^4.11.4", - "jose": "^6.1.3", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "@cfworker/json-schema": { - "optional": true - }, - "zod": { - "optional": false - } - } - }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -2061,19 +2006,6 @@ "win32" ] }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -2088,6 +2020,7 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -2100,23 +2033,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, "node_modules/ansi-escapes": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", @@ -2268,59 +2184,6 @@ "readable-stream": "^3.4.0" } }, - "node_modules/body-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", - "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^2.0.0", - "debug": "^4.4.3", - "http-errors": "^2.0.1", - "iconv-lite": "^0.7.2", - "on-finished": "^2.4.1", - "qs": "^6.15.2", - "raw-body": "^3.0.2", - "type-is": "^2.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/body-parser/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2420,15 +2283,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -2443,6 +2297,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -2456,6 +2311,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -2624,77 +2480,6 @@ "node": ">=18" } }, - "node_modules/content-disposition": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", - "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/css-select": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", @@ -2729,6 +2514,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2869,15 +2655,6 @@ "node": ">=0.4.0" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -2952,6 +2729,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -2989,12 +2767,6 @@ "url": "https://bevry.me/fund" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3002,15 +2774,6 @@ "dev": true, "license": "MIT" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/encoding-sniffer": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", @@ -3066,6 +2829,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3075,6 +2839,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3091,6 +2856,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -3156,12 +2922,6 @@ "@esbuild/win32-x64": "0.24.2" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -3172,36 +2932,6 @@ "@types/estree": "^1.0.0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.0.tgz", - "integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -3223,71 +2953,11 @@ "node": ">=12.0.0" } }, - "node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz", - "integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==", - "license": "MIT", - "dependencies": { - "ip-address": "^10.2.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -3311,6 +2981,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, "funding": [ { "type": "github", @@ -3346,27 +3017,6 @@ "node": ">=8" } }, - "node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", @@ -3428,24 +3078,6 @@ "node": ">= 0.6" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -3488,6 +3120,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3497,6 +3130,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -3521,6 +3155,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -3611,6 +3246,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3653,6 +3289,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3681,6 +3318,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -3689,15 +3327,6 @@ "node": ">= 0.4" } }, - "node_modules/hono": { - "version": "4.12.26", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.26.tgz", - "integrity": "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw==", - "license": "MIT", - "engines": { - "node": ">=16.9.0" - } - }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -3744,26 +3373,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -3854,7 +3463,9 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" + "dev": true, + "license": "ISC", + "optional": true }, "node_modules/ini": { "version": "1.3.8", @@ -3864,24 +3475,6 @@ "license": "ISC", "optional": true }, - "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -3986,12 +3579,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, "node_modules/is-wsl": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", @@ -4008,12 +3595,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, "node_modules/istextorbinary": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", @@ -4032,15 +3613,6 @@ "url": "https://bevry.me/fund" } }, - "node_modules/jose": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", - "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4075,14 +3647,9 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, "license": "MIT" }, - "node_modules/json-schema-typed": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", - "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", - "license": "BSD-2-Clause" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -4330,6 +3897,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4342,27 +3910,6 @@ "dev": true, "license": "MIT" }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4400,31 +3947,6 @@ "node": ">=4" } }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -4488,6 +4010,7 @@ "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/mute-stream": { @@ -4524,15 +4047,6 @@ "license": "MIT", "optional": true }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/node-abi": { "version": "3.92.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", @@ -4617,19 +4131,11 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4648,23 +4154,13 @@ "node": ">= 0.4" } }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "license": "ISC", + "optional": true, "dependencies": { "wrappy": "1" } @@ -4825,24 +4321,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/path-scurry": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", @@ -4870,16 +4348,6 @@ "node": "20 || >=22" } }, - "node_modules/path-to-regexp": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", - "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/path-type": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", @@ -4937,15 +4405,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkce-challenge": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", - "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -5014,19 +4473,6 @@ "node": ">=10" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/pump": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", @@ -5053,6 +4499,7 @@ "version": "6.15.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -5085,46 +4532,6 @@ ], "license": "MIT" }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -5221,6 +4628,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5282,22 +4690,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -5360,6 +4752,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, "license": "MIT" }, "node_modules/sax": { @@ -5407,82 +4800,11 @@ "node": ">=10" } }, - "node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/side-channel": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5502,6 +4824,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5518,6 +4841,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -5536,6 +4860,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -5701,15 +5026,6 @@ "dev": true, "license": "MIT" }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/std-env": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", @@ -6012,15 +5328,6 @@ "node": ">=8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -6065,37 +5372,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-is": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", - "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", - "license": "MIT", - "dependencies": { - "content-type": "^2.0.0", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/type-is/node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/typed-rest-client": { "version": "1.8.11", "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", @@ -6176,15 +5452,6 @@ "node": ">= 10.0.0" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -6211,15 +5478,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/version-range": { "version": "4.15.0", "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", @@ -6836,21 +6094,6 @@ "node": ">=18" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -6872,7 +6115,9 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" + "dev": true, + "license": "ISC", + "optional": true }, "node_modules/wsl-utils": { "version": "0.1.0", @@ -6958,24 +6203,6 @@ "dependencies": { "buffer-crc32": "~0.2.3" } - }, - "node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", - "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25.28 || ^4" - } } } } diff --git a/package.json b/package.json index f9ff212..5550cd5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "agentage-memory", - "displayName": "Agentage Memory", - "description": "Connect VS Code to your Agentage Memory in the cloud and search it over MCP.", + "name": "agentage", + "displayName": "Agentage", + "description": "Connect your editor's AI to your Agentage memory, over MCP.", "version": "0.0.1", "publisher": "agentage", "license": "MIT", @@ -51,8 +51,8 @@ "contributes": { "commands": [ { - "command": "agentage.searchMemory", - "title": "Search Memory", + "command": "agentage.connectEditor", + "title": "Connect Memory to this editor", "category": "Agentage" } ], @@ -77,9 +77,6 @@ "test": "vitest run", "test:watch": "vitest" }, - "dependencies": { - "@modelcontextprotocol/sdk": "^1.29.0" - }, "devDependencies": { "@types/node": "^22.10.0", "@types/vscode": "^1.85.0", diff --git a/src/auth.ts b/src/auth.ts deleted file mode 100644 index e829250..0000000 --- a/src/auth.ts +++ /dev/null @@ -1,148 +0,0 @@ -import * as vscode from 'vscode'; -import * as http from 'node:http'; -import type { AddressInfo } from 'node:net'; -import type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js'; -import type { - OAuthClientInformationFull, - OAuthClientMetadata, - OAuthTokens, -} from '@modelcontextprotocol/sdk/shared/auth.js'; -import { CLIENT_NAME, SCOPE } from './config'; - -const KEY_CLIENT = 'agentage.clientInformation'; -const KEY_TOKENS = 'agentage.tokens'; -const KEY_VERIFIER = 'agentage.codeVerifier'; - -type CallbackServer = { - server: http.Server; - port: number; - code: Promise; -}; - -function startLoopbackServer(): Promise { - return new Promise((resolve, reject) => { - let resolveCode!: (code: string) => void; - let rejectCode!: (err: Error) => void; - const code = new Promise((res, rej) => { - resolveCode = res; - rejectCode = rej; - }); - - const server = http.createServer((req, res) => { - const url = new URL(req.url ?? '/', 'http://127.0.0.1'); - if (url.pathname !== '/callback') { - res.writeHead(404); - res.end(); - return; - } - const authCode = url.searchParams.get('code'); - const error = url.searchParams.get('error'); - res.writeHead(200, { 'Content-Type': 'text/html' }); - res.end( - '' + - '

agentage Memory

Signed in. You can close this tab and return to your editor.

' - ); - if (error) rejectCode(new Error(`Authorization failed: ${error}`)); - else if (authCode) resolveCode(authCode); - else rejectCode(new Error('No authorization code in callback')); - }); - - server.on('error', reject); - server.listen(0, '127.0.0.1', () => { - const port = (server.address() as AddressInfo).port; - resolve({ server, port, code }); - }); - }); -} - -/** - * OAuth 2.1 + PKCE + DCR provider for the MCP SDK, backed by VS Code SecretStorage. - * The SDK drives DCR, PKCE and the token exchange; we only persist + open the browser - * and capture the loopback redirect. - */ -export class VsCodeOAuthProvider implements OAuthClientProvider { - private callback?: CallbackServer; - private _redirectUrl = 'http://127.0.0.1:0/callback'; - - constructor(private readonly secrets: vscode.SecretStorage) {} - - get redirectUrl(): string { - return this._redirectUrl; - } - - get clientMetadata(): OAuthClientMetadata { - return { - client_name: CLIENT_NAME, - redirect_uris: [this._redirectUrl], - grant_types: ['authorization_code', 'refresh_token'], - response_types: ['code'], - token_endpoint_auth_method: 'none', - scope: SCOPE, - }; - } - - async clientInformation(): Promise { - const raw = await this.secrets.get(KEY_CLIENT); - return raw ? (JSON.parse(raw) as OAuthClientInformationFull) : undefined; - } - - async saveClientInformation(info: OAuthClientInformationFull): Promise { - await this.secrets.store(KEY_CLIENT, JSON.stringify(info)); - } - - async tokens(): Promise { - const raw = await this.secrets.get(KEY_TOKENS); - return raw ? (JSON.parse(raw) as OAuthTokens) : undefined; - } - - async saveTokens(tokens: OAuthTokens): Promise { - await this.secrets.store(KEY_TOKENS, JSON.stringify(tokens)); - } - - async saveCodeVerifier(verifier: string): Promise { - await this.secrets.store(KEY_VERIFIER, verifier); - } - - async codeVerifier(): Promise { - const v = await this.secrets.get(KEY_VERIFIER); - if (!v) throw new Error('Missing PKCE code verifier'); - return v; - } - - async redirectToAuthorization(authorizationUrl: URL): Promise { - vscode.window.setStatusBarMessage( - `Agentage Memory: opening ${authorizationUrl.host} to sign in...`, - 6000 - ); - await vscode.env.openExternal(vscode.Uri.parse(authorizationUrl.toString())); - } - - async invalidateCredentials( - scope: 'all' | 'client' | 'tokens' | 'verifier' - ): Promise { - if (scope === 'all' || scope === 'client') await this.secrets.delete(KEY_CLIENT); - if (scope === 'all' || scope === 'tokens') await this.secrets.delete(KEY_TOKENS); - if (scope === 'all' || scope === 'verifier') await this.secrets.delete(KEY_VERIFIER); - } - - // --- loopback lifecycle, used by the client around an interactive connect --- - - async startCallback(): Promise { - this.callback = await startLoopbackServer(); - this._redirectUrl = `http://127.0.0.1:${this.callback.port}/callback`; - } - - waitForCode(): Promise { - if (!this.callback) throw new Error('Callback server not started'); - return this.callback.code; - } - - stopCallback(): void { - this.callback?.server.close(); - this.callback = undefined; - } - - async signOut(): Promise { - await this.invalidateCredentials('all'); - } -} diff --git a/src/config.ts b/src/config.ts index bbc0d1a..b2475bb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,11 +1,6 @@ import * as vscode from 'vscode'; -export const SCHEME = 'agentage-memory'; -export const CLIENT_NAME = 'agentage Memory (VS Code)'; - -// Read-only search needs only memory:read; offline_access keeps the refresh token. -export const SCOPE = 'memory:read offline_access'; - +/** The MCP endpoint registered with the editor's AI. Override to target a different stack. */ export function getMcpUrl(): string { const configured = vscode.workspace .getConfiguration('agentage') diff --git a/src/connect-core.ts b/src/connect-core.ts new file mode 100644 index 0000000..79e88c7 --- /dev/null +++ b/src/connect-core.ts @@ -0,0 +1,111 @@ +// Pure helpers for "Connect Memory to this editor" - no 'vscode' import, vitest-testable. +import { join } from 'node:path'; + +export type Host = 'vscode' | 'cursor' | 'windsurf' | 'vscodium' | 'unknown'; + +export const SERVER_ID = 'agentage-memory'; + +/** Branch on vscode.env.uriScheme (stable, lowercase), never appName. */ +export function detectHost(uriScheme: string): Host { + switch (uriScheme) { + case 'vscode': + case 'vscode-insiders': + return 'vscode'; + case 'cursor': + return 'cursor'; + case 'windsurf': + return 'windsurf'; + case 'vscodium': + return 'vscodium'; + default: + return 'unknown'; + } +} + +export interface FileTarget { + file: string; + key: 'mcpServers'; + entry: Record; +} + +/** + * Config-file target for the forks we write to (Cursor, Windsurf) - both use stable + * home-relative global paths. Returns null for VS Code/VSCodium/unknown (handled elsewhere). + * Note the per-editor field names: Cursor `url`, Windsurf `serverUrl`. + */ +export function fileTarget(host: Host, home: string, url: string): FileTarget | null { + switch (host) { + case 'cursor': + return { file: join(home, '.cursor', 'mcp.json'), key: 'mcpServers', entry: { url } }; + case 'windsurf': + return { + file: join(home, '.codeium', 'windsurf', 'mcp_config.json'), + key: 'mcpServers', + entry: { serverUrl: url }, + }; + default: + return null; + } +} + +/** Strip // and block comments + trailing commas, string-aware so https:// in values survives. */ +export function stripJsonc(text: string): string { + let out = ''; + let inStr = false; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + const n = text[i + 1]; + if (inStr) { + out += c; + if (c === '\\') { + out += n ?? ''; + i++; + } else if (c === '"') { + inStr = false; + } + continue; + } + if (c === '"') { + inStr = true; + out += c; + continue; + } + if (c === '/' && n === '/') { + while (i < text.length && text[i] !== '\n') i++; + continue; + } + if (c === '/' && n === '*') { + i += 2; + while (i < text.length && !(text[i] === '*' && text[i + 1] === '/')) i++; + i++; + continue; + } + out += c; + } + return out.replace(/,(\s*[}\]])/g, '$1'); +} + +/** Merge our server entry into an existing (possibly JSONC) config, preserving siblings. */ +export function mergeServer( + existing: string | null, + key: 'servers' | 'mcpServers', + id: string, + entry: Record +): string { + let root: Record = {}; + if (existing && existing.trim()) { + try { + const parsed = JSON.parse(stripJsonc(existing)); + if (parsed && typeof parsed === 'object') root = parsed as Record; + } catch { + root = {}; + } + } + const bag = + root[key] && typeof root[key] === 'object' + ? (root[key] as Record) + : {}; + bag[id] = entry; + root[key] = bag; + return JSON.stringify(root, null, 2) + '\n'; +} diff --git a/src/connect-editor.ts b/src/connect-editor.ts new file mode 100644 index 0000000..458f3a9 --- /dev/null +++ b/src/connect-editor.ts @@ -0,0 +1,73 @@ +import * as vscode from 'vscode'; +import * as fs from 'node:fs/promises'; +import * as os from 'node:os'; +import { dirname } from 'node:path'; +import { detectHost, fileTarget, mergeServer, SERVER_ID, type Host } from './connect-core'; +import { getMcpUrl } from './config'; + +const HOST_MSG: Partial> = { + vscode: + 'Agentage Memory: confirm the install dialog, then open Copilot Chat in Agent mode and sign in when prompted.', + cursor: + 'Agentage Memory added to Cursor. Open Settings > MCP, enable it, and sign in when prompted.', + windsurf: + 'Agentage Memory added to Windsurf. Open the Cascade MCP panel, click Refresh, then sign in.', +}; + +/** + * Registers the remote MCP server with the HOST editor's agent (Copilot / Cursor / Windsurf) + * so it can read your memory - distinct from the in-process client behind Search Memory. + */ +export async function connectEditor(): Promise { + const url = getMcpUrl(); + const host = detectHost(vscode.env.uriScheme); + + // Cursor / Windsurf: write their stable global config file (read-merge-write). + const target = fileTarget(host, os.homedir(), url); + if (target) { + try { + await fs.mkdir(dirname(target.file), { recursive: true }); + let existing: string | null = null; + try { + existing = await fs.readFile(target.file, 'utf8'); + } catch { + // no file yet + } + await fs.writeFile( + target.file, + mergeServer(existing, target.key, SERVER_ID, target.entry), + 'utf8' + ); + } catch (e) { + const msg = e instanceof Error ? e.message : String(e); + vscode.window.showErrorMessage(`Agentage Memory: could not write ${target.file}: ${msg}`); + return; + } + const pick = await vscode.window.showInformationMessage(HOST_MSG[host]!, 'Open config'); + if (pick === 'Open config') { + await vscode.window.showTextDocument(vscode.Uri.file(target.file)); + } + return; + } + + // VS Code: host-managed one-click install deeplink (global, persists, host runs OAuth). + if (host === 'vscode') { + const payload = encodeURIComponent(JSON.stringify({ name: SERVER_ID, type: 'http', url })); + const link = `${vscode.env.uriScheme}:mcp/install?${payload}`; + const opened = await vscode.env.openExternal(vscode.Uri.parse(link)); + if (opened) { + vscode.window.showInformationMessage(HOST_MSG.vscode!); + return; + } + } + + // VSCodium / unknown / deeplink declined: hand the user the URL to add manually. + const copy = 'Copy server URL'; + const pick = await vscode.window.showInformationMessage( + `Add this MCP server in your editor to let its AI read your memory: ${url}`, + copy + ); + if (pick === copy) { + await vscode.env.clipboard.writeText(url); + } +} diff --git a/src/doc-provider.ts b/src/doc-provider.ts deleted file mode 100644 index 0e656bd..0000000 --- a/src/doc-provider.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as vscode from 'vscode'; -import type { MemoryClient } from './mcp-client'; - -/** Serves memory bodies on the agentage-memory:// scheme. These docs are read-only. */ -export class MemoryDocProvider implements vscode.TextDocumentContentProvider { - constructor(private readonly memory: MemoryClient) {} - - async provideTextDocumentContent(uri: vscode.Uri): Promise { - const path = uri.path.replace(/^\/+/, ''); - try { - return await this.memory.read(path); - } catch (e) { - const message = e instanceof Error ? e.message : String(e); - return `> agentage Memory: failed to load \`${path}\`\n>\n> ${message}`; - } - } -} diff --git a/src/extension.ts b/src/extension.ts index a699ac1..3c2053a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,31 +1,12 @@ import * as vscode from 'vscode'; -import { VsCodeOAuthProvider } from './auth'; -import { MemoryClient } from './mcp-client'; -import { MemoryDocProvider } from './doc-provider'; -import { runSearch } from './search'; -import { SCHEME } from './config'; +import { connectEditor } from './connect-editor'; export function activate(context: vscode.ExtensionContext): void { - const auth = new VsCodeOAuthProvider(context.secrets); - const memory = new MemoryClient(auth); - - const signOut = async () => { - await memory.disconnect(); - await auth.signOut(); - vscode.window.showInformationMessage('Agentage Memory: signed out.'); - }; - context.subscriptions.push( - vscode.workspace.registerTextDocumentContentProvider( - SCHEME, - new MemoryDocProvider(memory) - ), - vscode.commands.registerCommand('agentage.searchMemory', () => - runSearch(memory, signOut) - ) + vscode.commands.registerCommand('agentage.connectEditor', () => connectEditor()) ); } export function deactivate(): void { - // nothing to tear down: the MCP client is stateless HTTP + // nothing to tear down } diff --git a/src/mcp-client.ts b/src/mcp-client.ts deleted file mode 100644 index 39f77ae..0000000 --- a/src/mcp-client.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { Client } from '@modelcontextprotocol/sdk/client/index.js'; -import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; -import { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js'; -import type { VsCodeOAuthProvider } from './auth'; -import { getMcpUrl } from './config'; -import { - extractBody, - mapSearchResults, - type MemoryHit, -} from './search-core'; - -type ToolResult = { - content?: Array<{ type: string; text?: string }>; - structuredContent?: unknown; -}; - -function textOf(result: ToolResult): string { - return (result.content ?? []) - .filter((c) => c.type === 'text' && typeof c.text === 'string') - .map((c) => c.text as string) - .join('\n'); -} - -function jsonOf(result: ToolResult): unknown { - if (result.structuredContent !== undefined) return result.structuredContent; - try { - return JSON.parse(textOf(result)); - } catch { - return {}; - } -} - -/** Lazily-connected MCP client for memory.agentage.io/mcp. Connects (with OAuth) once. */ -export class MemoryClient { - private client?: Client; - private connecting?: Promise; - - constructor(private readonly auth: VsCodeOAuthProvider) {} - - private async connect(): Promise { - if (this.client) return this.client; - if (this.connecting) return this.connecting; - this.connecting = this.doConnect(); - try { - return await this.connecting; - } finally { - this.connecting = undefined; - } - } - - private async doConnect(): Promise { - const url = new URL(getMcpUrl()); - await this.auth.startCallback(); - const client = new Client( - { name: 'agentage-vscode', version: '0.0.1' }, - { capabilities: {} } - ); - try { - const transport = new StreamableHTTPClientTransport(url, { - authProvider: this.auth, - }); - try { - await client.connect(transport); - } catch (e) { - if (!(e instanceof UnauthorizedError)) throw e; - // First run: browser is opening; capture the loopback redirect, exchange, reconnect. - const code = await this.auth.waitForCode(); - await transport.finishAuth(code); - const authed = new StreamableHTTPClientTransport(url, { - authProvider: this.auth, - }); - await client.connect(authed); - } - } finally { - this.auth.stopCallback(); - } - this.client = client; - return client; - } - - async search(query: string, limit = 20, signal?: AbortSignal): Promise { - const client = await this.connect(); - const result = (await client.callTool( - { name: 'memory__search', arguments: { query, limit } }, - undefined, - { signal } - )) as ToolResult; - return mapSearchResults(jsonOf(result)); - } - - async read(path: string): Promise { - const client = await this.connect(); - const result = (await client.callTool({ - name: 'memory__read', - arguments: { path }, - })) as ToolResult; - return extractBody(jsonOf(result), textOf(result)); - } - - async disconnect(): Promise { - try { - await this.client?.close(); - } catch { - // ignore - } - this.client = undefined; - } -} diff --git a/src/search-core.ts b/src/search-core.ts deleted file mode 100644 index d5adc60..0000000 --- a/src/search-core.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Pure helpers - no 'vscode' import, so they are unit-testable with vitest. - -export interface MemoryHit { - path: string; - title: string; - snippet: string; - score?: number; - updated?: string; -} - -export interface QuickItem { - label: string; - description: string; - detail?: string; -} - -/** Normalize a memory__search result (structuredContent or parsed JSON) into hits. */ -export function mapSearchResults(data: unknown): MemoryHit[] { - const results = (data as { results?: unknown })?.results; - if (!Array.isArray(results)) return []; - return results - .map((r): MemoryHit => { - const row = r as Record; - const path = String(row.path ?? ''); - return { - path, - title: String(row.title ?? row.path ?? 'Untitled'), - snippet: String(row.snippet ?? ''), - score: typeof row.score === 'number' ? row.score : undefined, - updated: typeof row.updated === 'string' ? row.updated : undefined, - }; - }) - .filter((h) => h.path.length > 0); -} - -/** A hit becomes a QuickPick row: title + path + matched snippet. */ -export function hitToQuickItem(hit: MemoryHit): QuickItem { - return { - label: hit.title, - description: hit.path, - detail: hit.snippet || undefined, - }; -} - -/** Strip the read-only doc body out of a memory__read tool result. */ -export function extractBody(data: unknown, fallbackText: string): string { - const body = (data as { body?: unknown })?.body; - return typeof body === 'string' ? body : fallbackText; -} diff --git a/src/search.ts b/src/search.ts deleted file mode 100644 index f1a184a..0000000 --- a/src/search.ts +++ /dev/null @@ -1,95 +0,0 @@ -import * as vscode from 'vscode'; -import type { MemoryClient } from './mcp-client'; -import { hitToQuickItem } from './search-core'; -import { SCHEME } from './config'; - -const DEBOUNCE_MS = 250; - -const settingsButton: vscode.QuickInputButton = { - iconPath: new vscode.ThemeIcon('gear'), - tooltip: 'Agentage Memory settings', -}; - -const signOutButton: vscode.QuickInputButton = { - iconPath: new vscode.ThemeIcon('sign-out'), - tooltip: 'Sign out of Agentage Memory', -}; - -/** The one feature: live search-as-you-type, open the hit read-only on accept. */ -export function runSearch(memory: MemoryClient, signOut: () => Thenable): void { - const qp = vscode.window.createQuickPick(); - qp.placeholder = 'Search your memory...'; - qp.buttons = [settingsButton, signOutButton]; - // memory__search is substring, so the snippet contains the query -> matchOnDetail - // keeps server hits visible past VS Code's own input filter. - qp.matchOnDescription = true; - qp.matchOnDetail = true; - - let timer: ReturnType | undefined; - let inflight: AbortController | undefined; - - const search = (value: string) => { - if (timer) clearTimeout(timer); - timer = setTimeout(async () => { - const query = value.trim(); - if (!query) { - qp.items = []; - return; - } - inflight?.abort(); - const controller = new AbortController(); - inflight = controller; - qp.busy = true; - try { - const hits = await memory.search(query, 20, controller.signal); - if (controller.signal.aborted) return; - qp.items = hits.map(hitToQuickItem); - } catch (e) { - if (controller.signal.aborted) return; - qp.items = []; - const message = e instanceof Error ? e.message : String(e); - vscode.window.setStatusBarMessage(`agentage Memory: ${message}`, 4000); - } finally { - if (!controller.signal.aborted) qp.busy = false; - } - }, DEBOUNCE_MS); - }; - - qp.onDidChangeValue(search); - - qp.onDidTriggerButton(async (button) => { - if (button === settingsButton) { - qp.hide(); - await vscode.commands.executeCommand( - 'workbench.action.openSettings', - '@ext:agentage.agentage-memory' - ); - } else if (button === signOutButton) { - qp.hide(); - await signOut(); - } - }); - - qp.onDidAccept(async () => { - const path = qp.selectedItems[0]?.description; - qp.hide(); - if (!path) return; - const uri = vscode.Uri.from({ scheme: SCHEME, path: `/${path}` }); - try { - const doc = await vscode.workspace.openTextDocument(uri); - await vscode.languages.setTextDocumentLanguage(doc, 'markdown'); - await vscode.window.showTextDocument(doc, { preview: true }); - } catch (e) { - const message = e instanceof Error ? e.message : String(e); - vscode.window.showErrorMessage(`agentage Memory: could not open ${path}: ${message}`); - } - }); - - qp.onDidHide(() => { - inflight?.abort(); - if (timer) clearTimeout(timer); - qp.dispose(); - }); - - qp.show(); -} diff --git a/test/connect-core.test.ts b/test/connect-core.test.ts new file mode 100644 index 0000000..a786b21 --- /dev/null +++ b/test/connect-core.test.ts @@ -0,0 +1,73 @@ +import { describe, it, expect } from 'vitest'; +import { detectHost, fileTarget, stripJsonc, mergeServer } from '../src/connect-core'; + +const URL = 'https://memory.agentage.io/mcp'; + +describe('detectHost', () => { + it('maps known schemes', () => { + expect(detectHost('vscode')).toBe('vscode'); + expect(detectHost('vscode-insiders')).toBe('vscode'); + expect(detectHost('cursor')).toBe('cursor'); + expect(detectHost('windsurf')).toBe('windsurf'); + expect(detectHost('vscodium')).toBe('vscodium'); + }); + it('falls back to unknown', () => { + expect(detectHost('something-else')).toBe('unknown'); + }); +}); + +describe('fileTarget', () => { + it('cursor uses mcpServers + url', () => { + const t = fileTarget('cursor', '/home/u', URL); + expect(t?.file).toBe('/home/u/.cursor/mcp.json'); + expect(t?.key).toBe('mcpServers'); + expect(t?.entry).toEqual({ url: URL }); + }); + it('windsurf uses mcpServers + serverUrl', () => { + const t = fileTarget('windsurf', '/home/u', URL); + expect(t?.file).toBe('/home/u/.codeium/windsurf/mcp_config.json'); + expect(t?.entry).toEqual({ serverUrl: URL }); + }); + it('returns null for vscode/vscodium/unknown', () => { + expect(fileTarget('vscode', '/home/u', URL)).toBeNull(); + expect(fileTarget('vscodium', '/home/u', URL)).toBeNull(); + expect(fileTarget('unknown', '/home/u', URL)).toBeNull(); + }); +}); + +describe('stripJsonc', () => { + it('preserves https:// inside strings', () => { + const out = stripJsonc(`{ "url": "${URL}" }`); + expect(JSON.parse(out).url).toBe(URL); + }); + it('strips line + block comments and trailing commas', () => { + const out = stripJsonc(`{ + // a comment + "a": 1, /* block */ + "b": 2, + }`); + expect(JSON.parse(out)).toEqual({ a: 1, b: 2 }); + }); +}); + +describe('mergeServer', () => { + it('creates a fresh config when none exists', () => { + const out = mergeServer(null, 'mcpServers', 'agentage-memory', { url: URL }); + expect(JSON.parse(out)).toEqual({ 'mcpServers': { 'agentage-memory': { url: URL } } }); + }); + it('preserves sibling servers', () => { + const existing = JSON.stringify({ mcpServers: { other: { url: 'http://x' } } }); + const out = mergeServer(existing, 'mcpServers', 'agentage-memory', { url: URL }); + const obj = JSON.parse(out); + expect(obj.mcpServers.other).toEqual({ url: 'http://x' }); + expect(obj.mcpServers['agentage-memory']).toEqual({ url: URL }); + }); + it('overwrites only our id and tolerates JSONC input', () => { + const existing = `{ + // user notes + "mcpServers": { "agentage-memory": { "url": "http://old" } }, + }`; + const out = mergeServer(existing, 'mcpServers', 'agentage-memory', { url: URL }); + expect(JSON.parse(out).mcpServers['agentage-memory']).toEqual({ url: URL }); + }); +}); diff --git a/test/search-core.test.ts b/test/search-core.test.ts deleted file mode 100644 index 1ab3fa1..0000000 --- a/test/search-core.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { - mapSearchResults, - hitToQuickItem, - extractBody, -} from '../src/search-core'; - -describe('mapSearchResults', () => { - it('maps a structured results array into hits', () => { - const hits = mapSearchResults({ - results: [ - { - path: 'work/tasks/plan.md', - title: 'Plan', - snippet: '...the plan is...', - score: 3, - updated: '2026-06-20', - }, - ], - }); - expect(hits).toEqual([ - { - path: 'work/tasks/plan.md', - title: 'Plan', - snippet: '...the plan is...', - score: 3, - updated: '2026-06-20', - }, - ]); - }); - - it('falls back to path as title when title is missing', () => { - const [hit] = mapSearchResults({ results: [{ path: 'a/b.md' }] }); - expect(hit.title).toBe('a/b.md'); - expect(hit.snippet).toBe(''); - }); - - it('drops entries without a path', () => { - const hits = mapSearchResults({ - results: [{ title: 'no path' }, { path: 'ok.md' }], - }); - expect(hits).toHaveLength(1); - expect(hits[0].path).toBe('ok.md'); - }); - - it('returns [] for missing or malformed input', () => { - expect(mapSearchResults(undefined)).toEqual([]); - expect(mapSearchResults({})).toEqual([]); - expect(mapSearchResults({ results: 'nope' })).toEqual([]); - }); -}); - -describe('hitToQuickItem', () => { - it('uses title as label and path as description', () => { - const item = hitToQuickItem({ - path: 'notes/x.md', - title: 'X', - snippet: 'hello', - }); - expect(item).toEqual({ label: 'X', description: 'notes/x.md', detail: 'hello' }); - }); - - it('omits empty detail', () => { - const item = hitToQuickItem({ path: 'x.md', title: 'X', snippet: '' }); - expect(item.detail).toBeUndefined(); - }); -}); - -describe('extractBody', () => { - it('prefers structured body', () => { - expect(extractBody({ body: 'hi' }, 'fallback')).toBe('hi'); - }); - - it('falls back to text when body is absent', () => { - expect(extractBody({}, 'fallback')).toBe('fallback'); - expect(extractBody(undefined, 'fallback')).toBe('fallback'); - }); -}); From c51d54ec7a9c6d1e0419c5827cb34d94bf613442 Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 02:24:18 +0200 Subject: [PATCH 05/11] chore: rename repo references to vscode-agentage --- README.md | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 94693d3..46026b9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Installs](https://img.shields.io/visual-studio-marketplace/i/agentage.agentage?label=installs)](https://marketplace.visualstudio.com/items?itemName=agentage.agentage) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) -![Copilot Chat answering from your Agentage memory through the MCP connection](https://github.com/agentage/vscode-memory/raw/master/media/demo.gif) +![Copilot Chat answering from your Agentage memory through the MCP connection](https://github.com/agentage/vscode-agentage/raw/master/media/demo.gif) One command wires your editor's AI - GitHub Copilot, Cursor, or Windsurf - to your Agentage memory at `memory.agentage.io/mcp`. Ask in chat, and the agent reads and answers from the same memory every AI you use shares. No copy-paste, no local export. diff --git a/package.json b/package.json index 5550cd5..4015660 100644 --- a/package.json +++ b/package.json @@ -31,10 +31,10 @@ "homepage": "https://memory.agentage.io", "repository": { "type": "git", - "url": "https://github.com/agentage/vscode-memory.git" + "url": "https://github.com/agentage/vscode-agentage.git" }, "bugs": { - "url": "https://github.com/agentage/vscode-memory/issues" + "url": "https://github.com/agentage/vscode-agentage/issues" }, "capabilities": { "untrustedWorkspaces": { From 4eb03b2c2f7d3a4c9c19185780d7041901531368 Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 02:43:48 +0200 Subject: [PATCH 06/11] test: integration tests driving connectEditor against a mocked vscode + temp HOME Asserts the real command writes the correct mcp.json per host (Cursor url, Windsurf serverUrl, merge-preserving), opens the VS Code mcp/install deeplink, handles unknown hosts, and honors agentage.mcpUrl. --- test/connect-editor.test.ts | 68 +++++++++++++++++++++++++++++++++++ test/vscode-mock.ts | 71 +++++++++++++++++++++++++++++++++++++ vitest.config.ts | 7 ++++ 3 files changed, 146 insertions(+) create mode 100644 test/connect-editor.test.ts create mode 100644 test/vscode-mock.ts diff --git a/test/connect-editor.test.ts b/test/connect-editor.test.ts new file mode 100644 index 0000000..3d62580 --- /dev/null +++ b/test/connect-editor.test.ts @@ -0,0 +1,68 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import * as fs from 'node:fs/promises'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { state, __reset } from './vscode-mock'; +import { connectEditor } from '../src/connect-editor'; + +const URL = 'https://memory.agentage.io/mcp'; +let home: string; + +beforeEach(async () => { + __reset(); + home = await fs.mkdtemp(path.join(os.tmpdir(), 'ag-home-')); + process.env.HOME = home; +}); + +describe('connectEditor - Cursor', () => { + it('writes ~/.cursor/mcp.json with mcpServers + url', async () => { + state.uriScheme = 'cursor'; + await connectEditor(); + const obj = JSON.parse(await fs.readFile(path.join(home, '.cursor', 'mcp.json'), 'utf8')); + expect(obj.mcpServers['agentage-memory']).toEqual({ url: URL }); + expect(state.infoMessages[0].message).toContain('Cursor'); + expect(state.openExternalCalls).toHaveLength(0); + }); +}); + +describe('connectEditor - Windsurf', () => { + it('writes mcp_config.json with serverUrl and preserves existing servers', async () => { + state.uriScheme = 'windsurf'; + const file = path.join(home, '.codeium', 'windsurf', 'mcp_config.json'); + await fs.mkdir(path.dirname(file), { recursive: true }); + await fs.writeFile(file, JSON.stringify({ mcpServers: { other: { url: 'http://x' } } })); + await connectEditor(); + const obj = JSON.parse(await fs.readFile(file, 'utf8')); + expect(obj.mcpServers.other).toEqual({ url: 'http://x' }); + expect(obj.mcpServers['agentage-memory']).toEqual({ serverUrl: URL }); + }); +}); + +describe('connectEditor - VS Code', () => { + it('opens the mcp/install deeplink and writes no file', async () => { + state.uriScheme = 'vscode'; + await connectEditor(); + expect(state.openExternalCalls).toHaveLength(1); + expect(state.openExternalCalls[0]).toContain('vscode:mcp/install?'); + expect(state.openExternalCalls[0]).toContain(encodeURIComponent(URL)); + }); +}); + +describe('connectEditor - unknown host', () => { + it('hands the user the server URL to add manually', async () => { + state.uriScheme = 'emacs'; + await connectEditor(); + expect(state.openExternalCalls).toHaveLength(0); + expect(state.infoMessages[0].message).toContain(URL); + }); +}); + +describe('connectEditor - respects agentage.mcpUrl override', () => { + it('registers the configured endpoint', async () => { + state.uriScheme = 'cursor'; + state.mcpUrl = 'https://memory.dev.agentage.io/mcp'; + await connectEditor(); + const obj = JSON.parse(await fs.readFile(path.join(home, '.cursor', 'mcp.json'), 'utf8')); + expect(obj.mcpServers['agentage-memory']).toEqual({ url: 'https://memory.dev.agentage.io/mcp' }); + }); +}); diff --git a/test/vscode-mock.ts b/test/vscode-mock.ts new file mode 100644 index 0000000..f4d7f67 --- /dev/null +++ b/test/vscode-mock.ts @@ -0,0 +1,71 @@ +// Minimal controllable mock of the 'vscode' module surface that connect-editor.ts +// and config.ts touch. Aliased to 'vscode' in vitest.config.ts. + +export const state = { + uriScheme: 'vscode', + mcpUrl: undefined as string | undefined, + infoReturn: undefined as string | undefined, + openExternalReturn: true, + infoMessages: [] as { message: string; items: string[] }[], + errorMessages: [] as string[], + openExternalCalls: [] as string[], + clipboard: [] as string[], + shownDocs: [] as string[], +}; + +export function __reset(): void { + state.uriScheme = 'vscode'; + state.mcpUrl = undefined; + state.infoReturn = undefined; + state.openExternalReturn = true; + state.infoMessages = []; + state.errorMessages = []; + state.openExternalCalls = []; + state.clipboard = []; + state.shownDocs = []; +} + +export const window = { + showInformationMessage: async (message: string, ...items: string[]) => { + state.infoMessages.push({ message, items }); + return state.infoReturn; + }, + showErrorMessage: async (message: string) => { + state.errorMessages.push(message); + return undefined; + }, + showTextDocument: async (uri: { toString(): string }) => { + state.shownDocs.push(uri.toString()); + return {}; + }, +}; + +export const workspace = { + getConfiguration: (_section: string) => ({ + get: (_key: string) => state.mcpUrl, + }), +}; + +export const env = { + get uriScheme() { + return state.uriScheme; + }, + openExternal: async (uri: { toString(): string }) => { + state.openExternalCalls.push(uri.toString()); + return state.openExternalReturn; + }, + clipboard: { + writeText: async (text: string) => { + state.clipboard.push(text); + }, + }, +}; + +export const Uri = { + parse: (s: string) => ({ toString: () => s }), + file: (p: string) => ({ toString: () => `file://${p}`, fsPath: p }), +}; + +export const commands = { + executeCommand: async () => undefined, +}; diff --git a/vitest.config.ts b/vitest.config.ts index fa69665..dc70be5 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,8 +1,15 @@ import { defineConfig } from 'vitest/config'; +import { fileURLToPath } from 'node:url'; export default defineConfig({ test: { include: ['test/**/*.test.ts'], environment: 'node', }, + resolve: { + // Resolve `import 'vscode'` to a controllable mock so the command code path runs. + alias: { + vscode: fileURLToPath(new URL('./test/vscode-mock.ts', import.meta.url)), + }, + }, }); From d48fdbc999905a6ff1c2383d8dc4470a47284900 Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 11:19:26 +0200 Subject: [PATCH 07/11] fix: pre-submission review - P0 config-clobber + P1s - P0: mergeServer now throws ConfigParseError on an unparseable/odd-shaped existing config; connectEditor refuses to write and offers Open/Copy instead (no data loss). - P1: stripJsonc handles trailing commas string-aware (no more corrupting values containing ',}'); array/non-object guards. - P1: fold VSCodium into the mcp/install deeplink; actionable manual fallback with Setup guide + recovery buttons; relabel Open-config button to the file name. - P1: engines.vscode ^1.99.0 (was ^1.85.0) + README note that one-click needs 1.101+. - P2: publish.yml tag<->version assert; ci.yml vsce-package gate. - Tests: 13 core + 7 integration (clobber-safety, comma round-trip, VSCodium deeplink). --- .github/workflows/ci.yml | 1 + .github/workflows/publish.yml | 2 + README.md | 2 + package-lock.json | 4 +- package.json | 4 +- src/connect-core.ts | 55 ++++++++++++++++++---- src/connect-editor.ts | 86 ++++++++++++++++++++++++++--------- test/connect-core.test.ts | 25 +++++++++- test/connect-editor.test.ts | 23 ++++++++++ test/vscode-mock.ts | 10 ++-- 10 files changed, 171 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3d1cf5..47a3e84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,3 +18,4 @@ jobs: - run: npm run check-types - run: npm test - run: npm run compile + - run: npx @vscode/vsce package --allow-missing-repository -o /tmp/agentage.vsix diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4f59110..66db707 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,6 +16,8 @@ jobs: - run: npm ci - run: npm run check-types - run: npm test + - name: Assert tag matches package.json version + run: test "v$(node -p "require('./package.json').version")" = "${GITHUB_REF_NAME}" - name: Publish to Open VSX (also produces the .vsix) id: ovsx uses: HaaLeo/publish-vscode-extension@v2 diff --git a/README.md b/README.md index 46026b9..02e0b19 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ The command registers `memory.agentage.io/mcp` (Streamable HTTP) with your edito VS Code (Copilot Agent mode), and via [Open VSX](https://open-vsx.org/extension/agentage/agentage): **Cursor, Windsurf, VSCodium**. +One-click install needs VS Code **1.101+** (authenticated MCP); on older builds the command falls back to a copy-the-URL prompt. Cursor and Windsurf are version-independent (the command writes their MCP config file). + ## Privacy The extension only writes the server URL into your editor's MCP config (or opens the install deeplink). It stores no tokens, collects no telemetry, and sends no data of its own. Sign-in and all memory access happen through your editor's own MCP client. diff --git a/package-lock.json b/package-lock.json index 5b4c44d..be07d24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "devDependencies": { "@types/node": "^22.10.0", - "@types/vscode": "^1.85.0", + "@types/vscode": "^1.99.0", "@vscode/vsce": "^3.9.2", "esbuild": "^0.24.0", "ovsx": "^0.10.11", @@ -18,7 +18,7 @@ "vitest": "^2.1.0" }, "engines": { - "vscode": "^1.85.0" + "vscode": "^1.99.0" } }, "node_modules/@azu/format-text": { diff --git a/package.json b/package.json index 4015660..c1b3408 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "MIT", "icon": "media/icon.png", "engines": { - "vscode": "^1.85.0" + "vscode": "^1.99.0" }, "categories": [ "Other" @@ -79,7 +79,7 @@ }, "devDependencies": { "@types/node": "^22.10.0", - "@types/vscode": "^1.85.0", + "@types/vscode": "^1.99.0", "@vscode/vsce": "^3.9.2", "esbuild": "^0.24.0", "ovsx": "^0.10.11", diff --git a/src/connect-core.ts b/src/connect-core.ts index 79e88c7..e16435c 100644 --- a/src/connect-core.ts +++ b/src/connect-core.ts @@ -5,6 +5,14 @@ export type Host = 'vscode' | 'cursor' | 'windsurf' | 'vscodium' | 'unknown'; export const SERVER_ID = 'agentage-memory'; +/** Thrown when an existing config is non-empty but not parseable - so we never clobber it. */ +export class ConfigParseError extends Error { + constructor(message: string) { + super(message); + this.name = 'ConfigParseError'; + } +} + /** Branch on vscode.env.uriScheme (stable, lowercase), never appName. */ export function detectHost(uriScheme: string): Host { switch (uriScheme) { @@ -48,7 +56,10 @@ export function fileTarget(host: Host, home: string, url: string): FileTarget | } } -/** Strip // and block comments + trailing commas, string-aware so https:// in values survives. */ +/** + * Strip // and block comments + trailing commas, string-aware so a string value + * containing https:// or a literal ",}" / ",]" survives intact. + */ export function stripJsonc(text: string): string { let out = ''; let inStr = false; @@ -80,12 +91,27 @@ export function stripJsonc(text: string): string { i++; continue; } + if (c === ',') { + // drop a trailing comma (only when the next non-space char closes a container) + let j = i + 1; + while (j < text.length && /\s/.test(text[j])) j++; + if (text[j] === '}' || text[j] === ']') continue; + out += c; + continue; + } out += c; } - return out.replace(/,(\s*[}\]])/g, '$1'); + return out; } -/** Merge our server entry into an existing (possibly JSONC) config, preserving siblings. */ +const isPlainObject = (v: unknown): v is Record => + typeof v === 'object' && v !== null && !Array.isArray(v); + +/** + * Merge our server entry into an existing (possibly JSONC) config, preserving siblings. + * Throws ConfigParseError when an existing non-empty file is not parseable or its shape + * is unexpected - the caller MUST NOT overwrite the file in that case (no data loss). + */ export function mergeServer( existing: string | null, key: 'servers' | 'mcpServers', @@ -94,17 +120,26 @@ export function mergeServer( ): string { let root: Record = {}; if (existing && existing.trim()) { + let parsed: unknown; try { - const parsed = JSON.parse(stripJsonc(existing)); - if (parsed && typeof parsed === 'object') root = parsed as Record; + parsed = JSON.parse(stripJsonc(existing)); } catch { - root = {}; + throw new ConfigParseError('existing config is not valid JSON/JSONC'); + } + if (!isPlainObject(parsed)) { + throw new ConfigParseError('existing config root is not an object'); } + root = parsed; + } + const existingBag = root[key]; + let bag: Record; + if (existingBag === undefined) { + bag = {}; + } else if (isPlainObject(existingBag)) { + bag = existingBag; + } else { + throw new ConfigParseError(`existing "${key}" is not an object`); } - const bag = - root[key] && typeof root[key] === 'object' - ? (root[key] as Record) - : {}; bag[id] = entry; root[key] = bag; return JSON.stringify(root, null, 2) + '\n'; diff --git a/src/connect-editor.ts b/src/connect-editor.ts index 458f3a9..96513f5 100644 --- a/src/connect-editor.ts +++ b/src/connect-editor.ts @@ -1,13 +1,24 @@ import * as vscode from 'vscode'; import * as fs from 'node:fs/promises'; import * as os from 'node:os'; -import { dirname } from 'node:path'; -import { detectHost, fileTarget, mergeServer, SERVER_ID, type Host } from './connect-core'; +import { dirname, basename } from 'node:path'; +import { + detectHost, + fileTarget, + mergeServer, + ConfigParseError, + SERVER_ID, + type Host, +} from './connect-core'; import { getMcpUrl } from './config'; +const REPO_HELP = 'https://github.com/agentage/vscode-agentage#how-it-works'; + const HOST_MSG: Partial> = { vscode: 'Agentage Memory: confirm the install dialog, then open Copilot Chat in Agent mode and sign in when prompted.', + vscodium: + 'Agentage Memory: confirm the install dialog, then use it from an MCP-capable chat and sign in when prompted.', cursor: 'Agentage Memory added to Cursor. Open Settings > MCP, enable it, and sign in when prompted.', windsurf: @@ -16,7 +27,7 @@ const HOST_MSG: Partial> = { /** * Registers the remote MCP server with the HOST editor's agent (Copilot / Cursor / Windsurf) - * so it can read your memory - distinct from the in-process client behind Search Memory. + * so it can read your memory. Never overwrites an unparseable config (no data loss). */ export async function connectEditor(): Promise { const url = getMcpUrl(); @@ -25,49 +36,80 @@ export async function connectEditor(): Promise { // Cursor / Windsurf: write their stable global config file (read-merge-write). const target = fileTarget(host, os.homedir(), url); if (target) { + let existing: string | null = null; try { - await fs.mkdir(dirname(target.file), { recursive: true }); - let existing: string | null = null; - try { - existing = await fs.readFile(target.file, 'utf8'); - } catch { - // no file yet + existing = await fs.readFile(target.file, 'utf8'); + } catch { + // no file yet + } + + let merged: string; + try { + merged = mergeServer(existing, target.key, SERVER_ID, target.entry); + } catch (e) { + if (e instanceof ConfigParseError) { + const open = 'Open config'; + const copy = 'Copy entry'; + const pick = await vscode.window.showErrorMessage( + `Agentage Memory: ${target.file} has invalid JSON, so it was left untouched. Add the server yourself.`, + open, + copy + ); + if (pick === open) { + await vscode.window.showTextDocument(vscode.Uri.file(target.file)); + } else if (pick === copy) { + await vscode.env.clipboard.writeText( + JSON.stringify({ [SERVER_ID]: target.entry }, null, 2) + ); + } + return; } - await fs.writeFile( - target.file, - mergeServer(existing, target.key, SERVER_ID, target.entry), - 'utf8' - ); + throw e; + } + + try { + await fs.mkdir(dirname(target.file), { recursive: true }); + await fs.writeFile(target.file, merged, 'utf8'); } catch (e) { const msg = e instanceof Error ? e.message : String(e); vscode.window.showErrorMessage(`Agentage Memory: could not write ${target.file}: ${msg}`); return; } - const pick = await vscode.window.showInformationMessage(HOST_MSG[host]!, 'Open config'); - if (pick === 'Open config') { + + const openBtn = `Open ${basename(target.file)}`; + const pick = await vscode.window.showInformationMessage(HOST_MSG[host]!, openBtn); + if (pick === openBtn) { await vscode.window.showTextDocument(vscode.Uri.file(target.file)); } return; } - // VS Code: host-managed one-click install deeplink (global, persists, host runs OAuth). - if (host === 'vscode') { + // VS Code / VSCodium: host-managed one-click install deeplink (host runs OAuth). + if (host === 'vscode' || host === 'vscodium') { const payload = encodeURIComponent(JSON.stringify({ name: SERVER_ID, type: 'http', url })); const link = `${vscode.env.uriScheme}:mcp/install?${payload}`; const opened = await vscode.env.openExternal(vscode.Uri.parse(link)); if (opened) { - vscode.window.showInformationMessage(HOST_MSG.vscode!); + const manual = 'Add manually'; + const pick = await vscode.window.showInformationMessage(HOST_MSG[host]!, manual); + if (pick === manual) { + await vscode.env.clipboard.writeText(url); + } return; } } - // VSCodium / unknown / deeplink declined: hand the user the URL to add manually. + // Unknown fork / declined deeplink: an actionable manual path, not a dead end. const copy = 'Copy server URL'; + const guide = 'Setup guide'; const pick = await vscode.window.showInformationMessage( - `Add this MCP server in your editor to let its AI read your memory: ${url}`, - copy + `Add Agentage as a Streamable HTTP MCP server (no command/args) in your editor: ${url}`, + copy, + guide ); if (pick === copy) { await vscode.env.clipboard.writeText(url); + } else if (pick === guide) { + await vscode.env.openExternal(vscode.Uri.parse(REPO_HELP)); } } diff --git a/test/connect-core.test.ts b/test/connect-core.test.ts index a786b21..94f93ce 100644 --- a/test/connect-core.test.ts +++ b/test/connect-core.test.ts @@ -1,5 +1,11 @@ import { describe, it, expect } from 'vitest'; -import { detectHost, fileTarget, stripJsonc, mergeServer } from '../src/connect-core'; +import { + detectHost, + fileTarget, + stripJsonc, + mergeServer, + ConfigParseError, +} from '../src/connect-core'; const URL = 'https://memory.agentage.io/mcp'; @@ -48,6 +54,10 @@ describe('stripJsonc', () => { }`); expect(JSON.parse(out)).toEqual({ a: 1, b: 2 }); }); + it('preserves a string value containing ",}" (no trailing-comma corruption)', () => { + const out = stripJsonc('{ "env": { "TOKEN": "ghp_x,}" }, }'); + expect(JSON.parse(out).env.TOKEN).toBe('ghp_x,}'); + }); }); describe('mergeServer', () => { @@ -70,4 +80,17 @@ describe('mergeServer', () => { const out = mergeServer(existing, 'mcpServers', 'agentage-memory', { url: URL }); expect(JSON.parse(out).mcpServers['agentage-memory']).toEqual({ url: URL }); }); + it('throws ConfigParseError on an unparseable non-empty file (never clobbers)', () => { + expect(() => mergeServer('{ "mcpServers": { broken', 'mcpServers', 'agentage-memory', { url: URL })).toThrow( + ConfigParseError + ); + }); + it('throws when the root or the servers key is not an object', () => { + expect(() => mergeServer('[1,2,3]', 'mcpServers', 'agentage-memory', { url: URL })).toThrow( + ConfigParseError + ); + expect(() => mergeServer('{ "mcpServers": [] }', 'mcpServers', 'agentage-memory', { url: URL })).toThrow( + ConfigParseError + ); + }); }); diff --git a/test/connect-editor.test.ts b/test/connect-editor.test.ts index 3d62580..1fc57aa 100644 --- a/test/connect-editor.test.ts +++ b/test/connect-editor.test.ts @@ -48,6 +48,29 @@ describe('connectEditor - VS Code', () => { }); }); +describe('connectEditor - VSCodium', () => { + it('uses the vscodium mcp/install deeplink', async () => { + state.uriScheme = 'vscodium'; + await connectEditor(); + expect(state.openExternalCalls).toHaveLength(1); + expect(state.openExternalCalls[0]).toContain('vscodium:mcp/install?'); + }); +}); + +describe('connectEditor - corrupt existing config', () => { + it('does NOT overwrite an unparseable Cursor config (no data loss)', async () => { + state.uriScheme = 'cursor'; + const file = path.join(home, '.cursor', 'mcp.json'); + await fs.mkdir(path.dirname(file), { recursive: true }); + const corrupt = '{ "mcpServers": { "other": { "url": "http://x" } '; // missing braces + await fs.writeFile(file, corrupt); + await connectEditor(); + expect(await fs.readFile(file, 'utf8')).toBe(corrupt); // untouched + expect(state.errorMessages).toHaveLength(1); + expect(state.errorMessages[0].message).toContain('invalid JSON'); + }); +}); + describe('connectEditor - unknown host', () => { it('hands the user the server URL to add manually', async () => { state.uriScheme = 'emacs'; diff --git a/test/vscode-mock.ts b/test/vscode-mock.ts index f4d7f67..612cee7 100644 --- a/test/vscode-mock.ts +++ b/test/vscode-mock.ts @@ -5,9 +5,10 @@ export const state = { uriScheme: 'vscode', mcpUrl: undefined as string | undefined, infoReturn: undefined as string | undefined, + errorReturn: undefined as string | undefined, openExternalReturn: true, infoMessages: [] as { message: string; items: string[] }[], - errorMessages: [] as string[], + errorMessages: [] as { message: string; items: string[] }[], openExternalCalls: [] as string[], clipboard: [] as string[], shownDocs: [] as string[], @@ -17,6 +18,7 @@ export function __reset(): void { state.uriScheme = 'vscode'; state.mcpUrl = undefined; state.infoReturn = undefined; + state.errorReturn = undefined; state.openExternalReturn = true; state.infoMessages = []; state.errorMessages = []; @@ -30,9 +32,9 @@ export const window = { state.infoMessages.push({ message, items }); return state.infoReturn; }, - showErrorMessage: async (message: string) => { - state.errorMessages.push(message); - return undefined; + showErrorMessage: async (message: string, ...items: string[]) => { + state.errorMessages.push({ message, items }); + return state.errorReturn; }, showTextDocument: async (uri: { toString(): string }) => { state.shownDocs.push(uri.toString()); From 99173a5b410f2965be0ed002c9172b76971c9c55 Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 11:29:48 +0200 Subject: [PATCH 08/11] chore: align with golden-standard (prettier-vscode) - esbuild problem-matcher, gh release on publish, drop stale vsce flag --- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 6 ++++++ esbuild.js | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47a3e84..d06d912 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,4 +18,4 @@ jobs: - run: npm run check-types - run: npm test - run: npm run compile - - run: npx @vscode/vsce package --allow-missing-repository -o /tmp/agentage.vsix + - run: npx @vscode/vsce package -o /tmp/agentage.vsix diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 66db707..5266201 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,6 +8,8 @@ on: jobs: publish: runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -29,3 +31,7 @@ jobs: pat: ${{ secrets.VS_MARKETPLACE_TOKEN }} registryUrl: https://marketplace.visualstudio.com extensionFile: ${{ steps.ovsx.outputs.vsixPath }} + - name: Create GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: gh release create "${GITHUB_REF_NAME}" --generate-notes "${{ steps.ovsx.outputs.vsixPath }}" diff --git a/esbuild.js b/esbuild.js index 863d5d3..b7a5131 100644 --- a/esbuild.js +++ b/esbuild.js @@ -3,6 +3,23 @@ const esbuild = require('esbuild'); const production = process.argv.includes('--production'); const watch = process.argv.includes('--watch'); +/** Surfaces build errors in the VS Code Problems panel during watch (F5 loop). */ +const problemMatcherPlugin = { + name: 'esbuild-problem-matcher', + setup(build) { + build.onStart(() => console.log('[watch] build started')); + build.onEnd((result) => { + for (const { text, location } of result.errors) { + console.error(`✘ [ERROR] ${text}`); + if (location) { + console.error(` ${location.file}:${location.line}:${location.column}:`); + } + } + console.log('[watch] build finished'); + }); + }, +}; + async function main() { const ctx = await esbuild.context({ entryPoints: ['src/extension.ts'], @@ -16,6 +33,7 @@ async function main() { sourcemap: !production, sourcesContent: false, logLevel: 'info', + plugins: [problemMatcherPlugin], }); if (watch) { await ctx.watch(); From e1959918bb00f42fe7a5182ebac2a9a78a1186bd Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 12:02:48 +0200 Subject: [PATCH 09/11] feat: auto-install the MCP server on setup (no command needed) - VS Code: native MCP provider (contributes.mcpServerDefinitionProviders + registerMcpServerDefinitionProvider, stable since 1.99) registered at activation (onStartupFinished) - the server appears in the MCP list automatically; VS Code runs OAuth on first use (one-time trust + sign-in; auth'd servers don't auto-start). - Cursor/Windsurf: autoConnectForks writes their config silently + idempotently on activation (hasServerEntry skip; never clobbers; errors swallowed). - Manual command kept for re-connect / unknown forks. engines stays ^1.99.0. - Tests: 15 core + 3 provider + 10 connect-editor = 28. README/CHANGELOG/CONTRIBUTING updated. --- CHANGELOG.md | 3 ++- CONTRIBUTING.md | 9 ++++++--- README.md | 19 +++++++++++-------- package.json | 10 +++++++++- src/connect-core.ts | 18 ++++++++++++++++++ src/connect-editor.ts | 26 ++++++++++++++++++++++++++ src/extension.ts | 9 ++++++++- src/mcp-provider.ts | 31 +++++++++++++++++++++++++++++++ test/connect-core.test.ts | 21 +++++++++++++++++++++ test/connect-editor.test.ts | 36 +++++++++++++++++++++++++++++++++++- test/mcp-provider.test.ts | 33 +++++++++++++++++++++++++++++++++ test/vscode-mock.ts | 36 ++++++++++++++++++++++++++++++++++++ 12 files changed, 236 insertions(+), 15 deletions(-) create mode 100644 src/mcp-provider.ts create mode 100644 test/mcp-provider.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba0f4c..744c05b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,5 +8,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added -- `Agentage: Connect Memory to this editor` - registers the Agentage MCP server (`memory.agentage.io/mcp`) with your editor's AI so it can read your memory. VS Code uses the install deeplink; Cursor and Windsurf get their config file written (merged, never clobbered). +- **Auto-install on setup** - the Agentage Memory server registers itself with your editor's AI on activation: VS Code via the native MCP provider API (appears in the MCP servers list, no command), Cursor and Windsurf via their config file (idempotent, merged, never clobbered). VS Code runs OAuth itself on first use (one-time trust + sign-in). +- `Agentage: Connect Memory to this editor` - the same registration on demand (manual re-connect / unknown forks; uses the VS Code install deeplink). - `agentage.mcpUrl` setting to target a different stack. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 040369b..a5f65ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,12 +21,15 @@ host editor's AI agent - it does not talk to MCP itself, and it has no runtime dependencies. The host editor runs OAuth 2.1 when its agent first uses the server. ``` -src/extension.ts activate(): registers the one command -src/connect-editor.ts host detection + register the server (VS Code deeplink / Cursor + Windsurf config file) -src/connect-core.ts pure helpers (host detect, per-editor JSON, JSONC-safe merge) - vitest-tested +src/extension.ts activate(): auto-register (provider + fork config) + the manual command +src/mcp-provider.ts VS Code native MCP provider (onStartupFinished) - server appears with no command +src/connect-editor.ts the manual command + autoConnectForks (silent idempotent Cursor/Windsurf write) +src/connect-core.ts pure helpers (host detect, per-editor JSON, JSONC-safe merge, idempotency check) - vitest-tested src/config.ts the agentage.mcpUrl setting ``` +Auto-install: VS Code is contributed via `contributes.mcpServerDefinitionProviders` + `registerMcpServerDefinitionProvider` (the id must match; activation is `onStartupFinished`). The forks have no such API, so the extension writes their config file directly. + Per-editor config shapes differ - VS Code `servers` + `type:http` + `url`, Cursor `mcpServers` + `url`, Windsurf `mcpServers` + `serverUrl` - so existing config is read-merged, never overwritten. diff --git a/README.md b/README.md index 02e0b19..c7e3383 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,14 @@ ![Copilot Chat answering from your Agentage memory through the MCP connection](https://github.com/agentage/vscode-agentage/raw/master/media/demo.gif) -One command wires your editor's AI - GitHub Copilot, Cursor, or Windsurf - to your Agentage memory at `memory.agentage.io/mcp`. Ask in chat, and the agent reads and answers from the same memory every AI you use shares. No copy-paste, no local export. +On install, Agentage registers your memory with your editor's AI - GitHub Copilot, Cursor, or Windsurf - at `memory.agentage.io/mcp`. Ask in chat, and the agent reads and answers from the same memory every AI you use shares. No command to run, no copy-paste, no local export. ## Features -- **One command** - `Agentage: Connect Memory to this editor` registers the Agentage MCP server with your editor's AI. +- **Auto-installed** - on setup the Agentage Memory server registers itself with your editor's AI (VS Code's MCP provider; Cursor / Windsurf config) and appears in the MCP servers list - no command to run. - **Works where you work** - VS Code (Copilot Agent mode), Cursor, and Windsurf. -- **Your editor handles sign-in** - OAuth 2.1 runs in the host's own MCP flow. The extension stores no tokens and sends no data of its own. +- **Your editor handles sign-in** - OAuth 2.1 runs in the host's own MCP flow on first use. The extension stores no tokens and sends no data of its own. +- **One-time switch-on** - the first time its agent uses the server, VS Code shows a trust prompt + browser sign-in (it does not auto-start authenticated servers, by design); after that it stays on. ## Requirements @@ -24,13 +25,15 @@ One command wires your editor's AI - GitHub Copilot, Cursor, or Windsurf - to yo ## Getting started -1. Run **`Agentage: Connect Memory to this editor`** from the Command Palette (`Ctrl/Cmd+Shift+P`). -2. VS Code: confirm the install dialog. Cursor / Windsurf: enable or refresh the server in the MCP panel. -3. Open your AI chat in agent mode and ask something from your memory - sign in when prompted. +1. Install the extension. The **Agentage Memory** server appears automatically in your editor's MCP servers list. +2. Open your AI chat in agent mode; on first use, approve the trust prompt and sign in. +3. Ask something from your memory. + +Didn't appear (older editor / unknown fork)? Run **`Agentage: Connect Memory to this editor`** from the Command Palette to register it manually. ## How it works -The command registers `memory.agentage.io/mcp` (Streamable HTTP) with your editor's MCP configuration - the VS Code install deeplink, or the Cursor / Windsurf config file (merged, never overwritten). Your editor's agent then connects and runs OAuth 2.1 itself. This extension stores no tokens and sends no data of its own. +On activation the extension registers `memory.agentage.io/mcp` (Streamable HTTP) with your editor: VS Code via the **MCP provider API** (stable since 1.99, so the server appears on startup), Cursor and Windsurf by writing their MCP config file (merged, never overwritten). Your editor's agent runs OAuth 2.1 itself on first use. This extension stores no tokens and sends no data of its own. The `Agentage: Connect Memory to this editor` command does the same registration on demand. ## Settings @@ -48,7 +51,7 @@ The command registers `memory.agentage.io/mcp` (Streamable HTTP) with your edito VS Code (Copilot Agent mode), and via [Open VSX](https://open-vsx.org/extension/agentage/agentage): **Cursor, Windsurf, VSCodium**. -One-click install needs VS Code **1.101+** (authenticated MCP); on older builds the command falls back to a copy-the-URL prompt. Cursor and Windsurf are version-independent (the command writes their MCP config file). +Auto-install needs VS Code **1.99+** (our minimum; the MCP provider API is stable from 1.99, authenticated MCP smoothest on 1.101+). Cursor and Windsurf are version-independent (the extension writes their MCP config file). ## Privacy diff --git a/package.json b/package.json index c1b3408..14e914c 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,16 @@ "workspace" ], "main": "./dist/extension.js", - "activationEvents": [], + "activationEvents": [ + "onStartupFinished" + ], "contributes": { + "mcpServerDefinitionProviders": [ + { + "id": "agentageMemory", + "label": "Agentage Memory" + } + ], "commands": [ { "command": "agentage.connectEditor", diff --git a/src/connect-core.ts b/src/connect-core.ts index e16435c..a34d261 100644 --- a/src/connect-core.ts +++ b/src/connect-core.ts @@ -107,6 +107,24 @@ export function stripJsonc(text: string): string { const isPlainObject = (v: unknown): v is Record => typeof v === 'object' && v !== null && !Array.isArray(v); +/** True if the config already contains our exact entry - lets auto-connect skip a rewrite. */ +export function hasServerEntry( + existing: string | null, + key: 'servers' | 'mcpServers', + id: string, + entry: Record +): boolean { + if (!existing || !existing.trim()) return false; + let parsed: unknown; + try { + parsed = JSON.parse(stripJsonc(existing)); + } catch { + return false; + } + if (!isPlainObject(parsed) || !isPlainObject(parsed[key])) return false; + return JSON.stringify((parsed[key] as Record)[id]) === JSON.stringify(entry); +} + /** * Merge our server entry into an existing (possibly JSONC) config, preserving siblings. * Throws ConfigParseError when an existing non-empty file is not parseable or its shape diff --git a/src/connect-editor.ts b/src/connect-editor.ts index 96513f5..990c4a1 100644 --- a/src/connect-editor.ts +++ b/src/connect-editor.ts @@ -6,12 +6,38 @@ import { detectHost, fileTarget, mergeServer, + hasServerEntry, ConfigParseError, SERVER_ID, type Host, } from './connect-core'; import { getMcpUrl } from './config'; +/** + * Best-effort, silent, idempotent auto-connect for Cursor / Windsurf on activation - + * writes their MCP config so the server is available without running a command. Skips if + * already present; never clobbers an unparseable config; swallows errors (startup path). + * VS Code is handled by the native MCP provider instead, so this no-ops there. + */ +export async function autoConnectForks(): Promise { + const target = fileTarget(detectHost(vscode.env.uriScheme), os.homedir(), getMcpUrl()); + if (!target) return; + try { + let existing: string | null = null; + try { + existing = await fs.readFile(target.file, 'utf8'); + } catch { + // no file yet + } + if (hasServerEntry(existing, target.key, SERVER_ID, target.entry)) return; + const merged = mergeServer(existing, target.key, SERVER_ID, target.entry); + await fs.mkdir(dirname(target.file), { recursive: true }); + await fs.writeFile(target.file, merged, 'utf8'); + } catch { + // best-effort: a corrupt/locked config is left untouched; the command surfaces errors + } +} + const REPO_HELP = 'https://github.com/agentage/vscode-agentage#how-it-works'; const HOST_MSG: Partial> = { diff --git a/src/extension.ts b/src/extension.ts index 3c2053a..7c387c0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,14 @@ import * as vscode from 'vscode'; -import { connectEditor } from './connect-editor'; +import { connectEditor, autoConnectForks } from './connect-editor'; +import { registerMcpProvider } from './mcp-provider'; export function activate(context: vscode.ExtensionContext): void { + // Auto-install the server so it's available without running a command: + // VS Code via the native MCP provider; Cursor/Windsurf via their config file. + registerMcpProvider(context); + void autoConnectForks(); + + // Manual command for re-connecting, unknown forks, or hosts the auto path skipped. context.subscriptions.push( vscode.commands.registerCommand('agentage.connectEditor', () => connectEditor()) ); diff --git a/src/mcp-provider.ts b/src/mcp-provider.ts new file mode 100644 index 0000000..cc46ccc --- /dev/null +++ b/src/mcp-provider.ts @@ -0,0 +1,31 @@ +import * as vscode from 'vscode'; +import { getMcpUrl } from './config'; + +// Must match contributes.mcpServerDefinitionProviders[].id in package.json. +const PROVIDER_ID = 'agentageMemory'; + +/** + * Auto-registers the Agentage Memory server with VS Code's MCP so it appears in the + * MCP servers list on startup - no command needed. Returns false (no-op) on editors + * without the native API (older VS Code, Cursor, Windsurf). VS Code drives OAuth itself + * the first time its agent starts the server (one-time trust + sign-in - it does not + * auto-start auth'd servers, by design). + */ +export function registerMcpProvider(context: vscode.ExtensionContext): boolean { + if (typeof vscode.lm?.registerMcpServerDefinitionProvider !== 'function') { + return false; + } + const didChange = new vscode.EventEmitter(); + const provider: vscode.McpServerDefinitionProvider = { + onDidChangeMcpServerDefinitions: didChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition('Agentage Memory', vscode.Uri.parse(getMcpUrl())), + ], + resolveMcpServerDefinition: (server) => server, + }; + context.subscriptions.push( + didChange, + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, provider) + ); + return true; +} diff --git a/test/connect-core.test.ts b/test/connect-core.test.ts index 94f93ce..06facfc 100644 --- a/test/connect-core.test.ts +++ b/test/connect-core.test.ts @@ -4,6 +4,7 @@ import { fileTarget, stripJsonc, mergeServer, + hasServerEntry, ConfigParseError, } from '../src/connect-core'; @@ -94,3 +95,23 @@ describe('mergeServer', () => { ); }); }); + +describe('hasServerEntry', () => { + it('true only when the exact entry is already present', () => { + const cfg = JSON.stringify({ mcpServers: { 'agentage-memory': { url: URL } } }); + expect(hasServerEntry(cfg, 'mcpServers', 'agentage-memory', { url: URL })).toBe(true); + }); + it('false for absent / different / null / corrupt', () => { + expect(hasServerEntry(null, 'mcpServers', 'agentage-memory', { url: URL })).toBe(false); + expect(hasServerEntry('{}', 'mcpServers', 'agentage-memory', { url: URL })).toBe(false); + expect( + hasServerEntry( + JSON.stringify({ mcpServers: { 'agentage-memory': { url: 'http://old' } } }), + 'mcpServers', + 'agentage-memory', + { url: URL } + ) + ).toBe(false); + expect(hasServerEntry('{ broken', 'mcpServers', 'agentage-memory', { url: URL })).toBe(false); + }); +}); diff --git a/test/connect-editor.test.ts b/test/connect-editor.test.ts index 1fc57aa..c6d21c3 100644 --- a/test/connect-editor.test.ts +++ b/test/connect-editor.test.ts @@ -3,7 +3,7 @@ import * as fs from 'node:fs/promises'; import * as os from 'node:os'; import * as path from 'node:path'; import { state, __reset } from './vscode-mock'; -import { connectEditor } from '../src/connect-editor'; +import { connectEditor, autoConnectForks } from '../src/connect-editor'; const URL = 'https://memory.agentage.io/mcp'; let home: string; @@ -57,6 +57,40 @@ describe('connectEditor - VSCodium', () => { }); }); +describe('autoConnectForks (silent install on activation)', () => { + it('writes the Cursor config silently and is idempotent', async () => { + state.uriScheme = 'cursor'; + await autoConnectForks(); + const file = path.join(home, '.cursor', 'mcp.json'); + expect(JSON.parse(await fs.readFile(file, 'utf8')).mcpServers['agentage-memory']).toEqual({ + url: URL, + }); + const before = await fs.readFile(file, 'utf8'); + await autoConnectForks(); // second run is a no-op + expect(await fs.readFile(file, 'utf8')).toBe(before); + expect(state.infoMessages).toHaveLength(0); + expect(state.errorMessages).toHaveLength(0); + }); + + it('no-ops on VS Code (the native provider handles it)', async () => { + state.uriScheme = 'vscode'; + await autoConnectForks(); + await expect(fs.readFile(path.join(home, '.cursor', 'mcp.json'), 'utf8')).rejects.toThrow(); + expect(state.errorMessages).toHaveLength(0); + }); + + it('leaves a corrupt config untouched and stays silent', async () => { + state.uriScheme = 'windsurf'; + const file = path.join(home, '.codeium', 'windsurf', 'mcp_config.json'); + await fs.mkdir(path.dirname(file), { recursive: true }); + const corrupt = '{ "mcpServers": { broken'; + await fs.writeFile(file, corrupt); + await autoConnectForks(); + expect(await fs.readFile(file, 'utf8')).toBe(corrupt); + expect(state.errorMessages).toHaveLength(0); + }); +}); + describe('connectEditor - corrupt existing config', () => { it('does NOT overwrite an unparseable Cursor config (no data loss)', async () => { state.uriScheme = 'cursor'; diff --git a/test/mcp-provider.test.ts b/test/mcp-provider.test.ts new file mode 100644 index 0000000..5334430 --- /dev/null +++ b/test/mcp-provider.test.ts @@ -0,0 +1,33 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { state, __reset } from './vscode-mock'; +import { registerMcpProvider } from '../src/mcp-provider'; + +const ctx = () => ({ subscriptions: [] as { dispose(): void }[] }); + +beforeEach(() => __reset()); + +describe('registerMcpProvider', () => { + it('registers the native provider under the contributes id', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const ok = registerMcpProvider(ctx() as any); + expect(ok).toBe(true); + expect(state.mcpProviderId).toBe('agentageMemory'); + }); + + it('provides one http server definition for the configured url', async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + registerMcpProvider(ctx() as any); + const defs = await state.mcpProvider.provideMcpServerDefinitions(); + expect(defs).toHaveLength(1); + expect(defs[0].label).toBe('Agentage Memory'); + expect(defs[0].uri.toString()).toBe('https://memory.agentage.io/mcp'); + }); + + it('honors the agentage.mcpUrl override', async () => { + state.mcpUrl = 'https://memory.dev.agentage.io/mcp'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + registerMcpProvider(ctx() as any); + const defs = await state.mcpProvider.provideMcpServerDefinitions(); + expect(defs[0].uri.toString()).toBe('https://memory.dev.agentage.io/mcp'); + }); +}); diff --git a/test/vscode-mock.ts b/test/vscode-mock.ts index 612cee7..71395a9 100644 --- a/test/vscode-mock.ts +++ b/test/vscode-mock.ts @@ -12,6 +12,9 @@ export const state = { openExternalCalls: [] as string[], clipboard: [] as string[], shownDocs: [] as string[], + mcpProviderId: undefined as string | undefined, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + mcpProvider: undefined as any, }; export function __reset(): void { @@ -25,6 +28,8 @@ export function __reset(): void { state.openExternalCalls = []; state.clipboard = []; state.shownDocs = []; + state.mcpProviderId = undefined; + state.mcpProvider = undefined; } export const window = { @@ -71,3 +76,34 @@ export const Uri = { export const commands = { executeCommand: async () => undefined, }; + +export class EventEmitter { + private listeners: ((e: T) => void)[] = []; + event = (listener: (e: T) => void) => { + this.listeners.push(listener); + return { dispose: () => undefined }; + }; + fire(e: T): void { + for (const l of this.listeners) l(e); + } + dispose(): void { + this.listeners = []; + } +} + +export class McpHttpServerDefinition { + constructor( + public label: string, + public uri: { toString(): string }, + public headers?: Record, + public version?: string + ) {} +} + +export const lm = { + registerMcpServerDefinitionProvider: (id: string, provider: unknown) => { + state.mcpProviderId = id; + state.mcpProvider = provider; + return { dispose: () => undefined }; + }, +}; From fd5e220be9fedd897f0c1f55c33689d435e3a880 Mon Sep 17 00:00:00 2001 From: vreshch Date: Sun, 21 Jun 2026 12:09:18 +0200 Subject: [PATCH 10/11] ci: re-trigger checks From f1acf7da987b162a1b0111fcdc96586413ebf8e4 Mon Sep 17 00:00:00 2001 From: Volodymyr Vreshch Date: Sun, 21 Jun 2026 19:27:01 +0200 Subject: [PATCH 11/11] test: add extension-host activation smoke (@vscode/test-cli) (#2) Real-VS-Code smoke proving the packaged extension activates, registers agentage.connectEditor, and contributes the default mcpUrl - the gap the vitest unit tests (logic-only, mocked vscode) can't cover. Wired into CI behind Xvfb; uploads the .vsix artifact for the e2e vscode project. --- .github/workflows/ci.yml | 8 + .vscode-test.mjs | 9 + .vscodeignore | 3 + package-lock.json | 1852 ++++++++++++++++++++++++++++++++-- package.json | 5 +- test-host/activation.test.js | 54 + 6 files changed, 1872 insertions(+), 59 deletions(-) create mode 100644 .vscode-test.mjs create mode 100644 test-host/activation.test.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d06d912..7ef1e52 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,5 +17,13 @@ jobs: - run: npm ci - run: npm run check-types - run: npm test + # Extension-host smoke in a real VS Code (headless via Xvfb). + - run: xvfb-run -a npm run test:host - run: npm run compile - run: npx @vscode/vsce package -o /tmp/agentage.vsix + # Hand the packaged .vsix to the e2e repo's `vscode` integration project. + - uses: actions/upload-artifact@v4 + with: + name: agentage-vsix + path: /tmp/agentage.vsix + if-no-files-found: error diff --git a/.vscode-test.mjs b/.vscode-test.mjs new file mode 100644 index 0000000..869f16e --- /dev/null +++ b/.vscode-test.mjs @@ -0,0 +1,9 @@ +import { defineConfig } from '@vscode/test-cli'; + +// Runs the host smoke (test-host/**) inside a real downloaded VS Code, loading the +// built extension from ./dist (run `npm run compile` first; `test:host` does). +export default defineConfig({ + files: 'test-host/**/*.test.js', + version: 'stable', + mocha: { ui: 'tdd', timeout: 20000 }, +}); diff --git a/.vscodeignore b/.vscodeignore index cf45adf..002e558 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,6 +1,9 @@ .vscode/** +.vscode-test/** +.vscode-test.mjs src/** test/** +test-host/** node_modules/** esbuild.js tsconfig.json diff --git a/package-lock.json b/package-lock.json index be07d24..9c93195 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,8 @@ "devDependencies": { "@types/node": "^22.10.0", "@types/vscode": "^1.99.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.4.1", "@vscode/vsce": "^3.9.2", "esbuild": "^0.24.0", "ovsx": "^0.10.11", @@ -231,6 +233,13 @@ "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, "node_modules/@emnapi/core": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", @@ -690,6 +699,100 @@ "node": ">=18" } }, + "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==", + "dev": true, + "license": "ISC", + "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/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -697,6 +800,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -1016,6 +1130,17 @@ "node": ">= 8" } }, + "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==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.62.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", @@ -1655,6 +1780,20 @@ "dev": true, "license": "MIT" }, + "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", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.20.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz", @@ -1814,6 +1953,139 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vscode/test-cli": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.10.tgz", + "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@vscode/test-cli/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vscode/test-cli/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vscode/test-cli/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-cli/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vscode/test-cli/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-cli/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==", + "dev": true, + "license": "BlueOak-1.0.0", + "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/@vscode/test-cli/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.5.2.tgz", + "integrity": "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^8.1.0", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@vscode/vsce": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.9.2.tgz", @@ -2033,6 +2305,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", @@ -2078,6 +2360,20 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2155,6 +2451,19 @@ "license": "MIT", "optional": true }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/binaryextensions": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", @@ -2224,6 +2533,13 @@ "node": ">=8" } }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -2283,6 +2599,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/c8": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz", + "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=14.14.0" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -2324,6 +2666,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", @@ -2412,6 +2767,31 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -2427,57 +2807,160 @@ "dev": true, "license": "MIT" }, - "node_modules/cockatiel": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", - "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "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==", "dev": true, "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, "engines": { - "node": ">=16" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "delayed-stream": "~1.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=12" } }, - "node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, "node_modules/css-select": { @@ -2528,6 +3011,19 @@ } } }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -2666,6 +3162,16 @@ "node": ">=8" } }, + "node_modules/diff": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -2740,6 +3246,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==", + "dev": true, + "license": "MIT" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -2799,6 +3312,20 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.0.tgz", + "integrity": "sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -2922,6 +3449,29 @@ "@esbuild/win32-x64": "0.24.2" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -3017,6 +3567,33 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", @@ -3038,6 +3615,23 @@ } } }, + "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==", + "dev": true, + "license": "ISC", + "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.6", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", @@ -3101,6 +3695,13 @@ "node": ">=14.14" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3126,6 +3727,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -3327,6 +3951,16 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -3340,6 +3974,13 @@ "node": ">=10" } }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, "node_modules/htmlparser2": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", @@ -3446,6 +4087,13 @@ "node": ">= 4" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, "node_modules/index-to-position": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", @@ -3459,13 +4107,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, - "license": "ISC", - "optional": true + "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", @@ -3475,6 +4134,19 @@ "license": "ISC", "optional": true }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -3556,6 +4228,19 @@ "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", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-it-type": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/is-it-type/-/is-it-type-5.1.3.tgz", @@ -3579,6 +4264,29 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-wsl": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", @@ -3595,26 +4303,95 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istextorbinary": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", - "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "Artistic-2.0", - "dependencies": { - "binaryextensions": "^6.11.0", - "editions": "^6.21.0", - "textextensions": "^6.11.0" - }, - "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" - } + "license": "MIT" }, - "node_modules/js-tokens": { - "version": "4.0.0", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "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==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, @@ -3706,6 +4483,52 @@ "npm": ">=6" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/jwa": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", @@ -3752,6 +4575,16 @@ "node": ">=6" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/linkify-it": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", @@ -3772,6 +4605,22 @@ "uc.micro": "^2.0.0" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", @@ -3835,6 +4684,23 @@ "dev": true, "license": "MIT" }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/loupe": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", @@ -3865,6 +4731,22 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/markdown-it": { "version": "14.2.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", @@ -3947,6 +4829,19 @@ "node": ">=4" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -4006,6 +4901,186 @@ "license": "MIT", "optional": true }, + "node_modules/mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", + "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4118,6 +5193,16 @@ "dev": true, "license": "ISC" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -4160,11 +5245,26 @@ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", - "optional": true, "dependencies": { "wrappy": "1" } }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/open": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", @@ -4184,6 +5284,111 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ovsx": { "version": "0.10.12", "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.10.12.tgz", @@ -4217,6 +5422,38 @@ "node": ">= 6" } }, + "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/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-map": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", @@ -4230,6 +5467,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/parse-json": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", @@ -4321,6 +5572,36 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-scurry": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", @@ -4473,6 +5754,13 @@ "node": ">=10" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", @@ -4532,6 +5820,16 @@ ], "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4624,6 +5922,29 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -4634,6 +5955,23 @@ "node": ">=0.10.0" } }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -4797,7 +6135,47 @@ "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/side-channel": { @@ -4883,6 +6261,19 @@ "dev": true, "license": "ISC" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", @@ -5033,6 +6424,19 @@ "dev": true, "license": "MIT" }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5059,6 +6463,45 @@ "node": ">=8" } }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string-width/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -5098,6 +6541,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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -5189,6 +6656,20 @@ "node": ">=8" } }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -5238,6 +6719,74 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "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": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "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.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5464,8 +7013,22 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } }, "node_modules/validate-npm-package-license": { "version": "3.0.4", @@ -6094,6 +7657,22 @@ "node": ">=18" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -6111,13 +7690,102 @@ "node": ">=8" } }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "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", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, - "license": "ISC", - "optional": true + "license": "ISC" }, "node_modules/wsl-utils": { "version": "0.1.0", @@ -6159,6 +7827,16 @@ "node": ">=4.0" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -6166,6 +7844,51 @@ "dev": true, "license": "ISC" }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/yauzl": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", @@ -6203,6 +7926,19 @@ "dependencies": { "buffer-crc32": "~0.2.3" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 14e914c..0bb38a1 100644 --- a/package.json +++ b/package.json @@ -83,11 +83,14 @@ "package": "node esbuild.js --production", "check-types": "tsc --noEmit", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "test:host": "npm run compile && vscode-test" }, "devDependencies": { "@types/node": "^22.10.0", "@types/vscode": "^1.99.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.4.1", "@vscode/vsce": "^3.9.2", "esbuild": "^0.24.0", "ovsx": "^0.10.11", diff --git a/test-host/activation.test.js b/test-host/activation.test.js new file mode 100644 index 0000000..9772e4a --- /dev/null +++ b/test-host/activation.test.js @@ -0,0 +1,54 @@ +// Extension-host smoke — runs inside a REAL VS Code via @vscode/test-cli. +// Proves the PACKAGED extension activates and contributes what it claims; the +// branch logic (host detection, JSONC merge, no-clobber) stays in the vitest +// unit tests. Network-free: under the test host uriScheme === 'vscode', so +// connectEditor takes the mcp/install deeplink branch — we assert it resolves, +// we never drive the OS install dialog (not headlessly automatable). +const assert = require('node:assert'); +const vscode = require('vscode'); + +const EXTENSION_ID = 'agentage.agentage'; +const COMMAND_ID = 'agentage.connectEditor'; +const DEFAULT_MCP_URL = 'https://memory.agentage.io/mcp'; + +suite('Agentage extension — activation smoke', () => { + // R1 — the packaged extension activates without an unhandled error. + test('activates without error (R1)', async () => { + const ext = vscode.extensions.getExtension(EXTENSION_ID); + assert.ok(ext, `extension ${EXTENSION_ID} not found in the host`); + await ext.activate(); + assert.strictEqual(ext.isActive, true); + }); + + // R2 — the command is registered after activation. + test('registers agentage.connectEditor (R2)', async () => { + const commands = await vscode.commands.getCommands(true); + assert.ok(commands.includes(COMMAND_ID), `${COMMAND_ID} is not registered`); + }); + + // R3 — invoking the command launches its handler without an early throw. + // On the VS Code path connectEditor opens the mcp/install deeplink and then + // awaits a user-facing info dialog, so it stays PENDING headlessly (O2). We + // assert it does not reject early — proving the handler runs (imports resolve, + // host detection + URL build don't blow up), not that the dialog is answered. + test('connectEditor launches without rejecting early (R3)', async () => { + const run = Promise.resolve(vscode.commands.executeCommand(COMMAND_ID)); + const outcome = await Promise.race([ + run.then( + () => 'resolved', + (err) => ({ rejected: err }) + ), + new Promise((resolve) => setTimeout(() => resolve('pending'), 1500)), + ]); + assert.ok( + outcome === 'pending' || outcome === 'resolved', + `connectEditor rejected early: ${outcome && outcome.rejected}` + ); + }); + + // R4 — the contributed config defaults to the prod MCP endpoint. + test('agentage.mcpUrl defaults to the prod endpoint (R4)', () => { + const url = vscode.workspace.getConfiguration('agentage').get('mcpUrl'); + assert.strictEqual(url, DEFAULT_MCP_URL); + }); +});