From 0078b2037075ccf52a1b6c6c4c8c01e9e76e207d Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Thu, 2 Jul 2026 15:04:13 -0700 Subject: [PATCH 1/8] feat: add mcp command group to manage the WorkOS MCP server in coding agents Adds `workos mcp install|remove|status` plus a client-writer library (src/lib/mcp-clients.ts) that configures the secret-free WorkOS MCP server (https://mcp.workos.com/mcp, HTTP transport) in Claude Code, Codex, and Cursor. - Claude Code / Codex via their own CLIs; Cursor via a jsonc-parser merge of ~/.cursor/mcp.json that preserves comments, trailing commas, and other servers - Every per-agent operation degrades to a reported outcome, never throws - Both human and JSON output modes; no auth guard (config is secret-free) - Codex eagerly starts OAuth on add and exits non-zero despite persisting the server, so add() verifies actual config state before reporting failure Review: 1 cycle, PASS (0 critical/high). --- package.json | 1 + pnpm-lock.yaml | 2722 +++++++++++--------------------------- src/bin.ts | 45 + src/commands/mcp.spec.ts | 431 ++++++ src/commands/mcp.ts | 136 ++ src/lib/constants.ts | 10 + src/lib/mcp-clients.ts | 310 +++++ src/utils/help-json.ts | 38 + 8 files changed, 1760 insertions(+), 1933 deletions(-) create mode 100644 src/commands/mcp.spec.ts create mode 100644 src/commands/mcp.ts create mode 100644 src/lib/mcp-clients.ts diff --git a/package.json b/package.json index d8282460..97eb8ed7 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "fast-glob": "^3.3.3", "hono": "^4", "ink": "^6.8.0", + "jsonc-parser": "^3.3.1", "open": "^11.0.0", "react": "^19.2.4", "semver": "^7.7.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4d06e60..683c4b49 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,19 +10,19 @@ importers: dependencies: '@anthropic-ai/claude-agent-sdk': specifier: ~0.3.0 - version: 0.3.198(@anthropic-ai/sdk@0.106.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) + version: 0.3.201(@anthropic-ai/sdk@0.106.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) '@anthropic-ai/sdk': specifier: ^0.106.0 version: 0.106.0(zod@4.4.3) '@clack/core': specifier: ^1.0.1 - version: 1.4.2 + version: 1.4.3 '@clack/prompts': specifier: 1.6.0 version: 1.6.0 '@hono/node-server': specifier: ^1 - version: 1.19.14(hono@4.11.4) + version: 1.19.14(hono@4.12.28) '@napi-rs/keyring': specifier: ^1.2.0 version: 1.3.0 @@ -31,7 +31,7 @@ importers: version: 8.13.0 '@workos/migrations': specifier: ^2.4.0 - version: 2.4.0 + version: 2.5.0 '@workos/openapi-spec': specifier: ^0.14.0 version: 0.14.0 @@ -49,10 +49,13 @@ importers: version: 3.3.3 hono: specifier: ^4 - version: 4.11.4 + version: 4.12.28 ink: specifier: ^6.8.0 version: 6.8.0(@types/react@19.2.17)(react@19.2.7) + jsonc-parser: + specifier: ^3.3.1 + version: 3.3.1 open: specifier: ^11.0.0 version: 11.0.0 @@ -67,7 +70,7 @@ importers: version: 13.0.2 xstate: specifier: ^5.28.0 - version: 5.32.2 + version: 5.32.4 yaml: specifier: ^2.8.2 version: 2.9.0 @@ -80,7 +83,7 @@ importers: devDependencies: '@statelyai/inspect': specifier: ^0.7.0 - version: 0.7.2(xstate@5.32.2) + version: 0.7.2(xstate@5.32.4) '@types/node': specifier: ~22.20.0 version: 22.20.0 @@ -98,10 +101,10 @@ importers: version: 17.0.35 '@vitest/coverage-v8': specifier: ^4.0.18 - version: 4.1.9(vitest@4.1.9) + version: 4.1.10(vitest@4.1.10) '@vitest/ui': specifier: ^4.0.18 - version: 4.1.9(vitest@4.1.9) + version: 4.1.10(vitest@4.1.10) dotenv: specifier: ^17.3.1 version: 17.4.2 @@ -110,19 +113,19 @@ importers: version: 0.56.0 oxlint: specifier: ^1.50.0 - version: 1.71.0 + version: 1.72.0 p-limit: specifier: ^7.3.0 version: 7.3.0 tsx: specifier: ^4.20.3 - version: 4.22.4 + version: 4.23.0 typescript: specifier: ^5.9.3 version: 5.9.3 vitest: specifier: ^4.0.18 - version: 4.1.9(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.9)(@vitest/ui@4.1.9)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) packages: @@ -130,52 +133,52 @@ packages: resolution: {integrity: sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw==} engines: {node: '>=18'} - '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.198': - resolution: {integrity: sha512-ZmiAybQKIKcP1qEAE/vfXvfxtKxG9CnJn98QTXC5Zxiwuy7Mllx2ALXh9dfmsf0V87CGEodlZQmMgUJotNIsUw==} + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.201': + resolution: {integrity: sha512-8Mcb3BDyKUGfJWFFTWwt+at37lbDH3ZwVtUNPWGG1toZ75RDCJry5U4kXRvQ2xokvJQlA0E+eNp6keWe5ZH22Q==} cpu: [arm64] os: [darwin] - '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.198': - resolution: {integrity: sha512-XwH5vgN46WSwg8aC1OagNofnJpV/G1ciEu118GEKer8ZhVkq/dvK/DqShxMkb6r1jV7u5IJ7zPXu9uKliyNJAw==} + '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.201': + resolution: {integrity: sha512-TFR2bu0+ml3RHoMrtsgD0qDK5Oknw8kYGBV7qpQHn+IWmE96gnHhogG1LpJwpHtni08XkJIjfWk1DdlsUYtRkQ==} cpu: [x64] os: [darwin] - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.198': - resolution: {integrity: sha512-Q7lKVNjIrUQ2B/AR77OvRf0zeOdEjonFVaR9FYrrwtzGeEqum69WSht5nM7Y7el3wjbNi0/eV0QTUM0DlsTEfw==} + '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.201': + resolution: {integrity: sha512-EiqbpfJIpChfkn+8Uj061Qjyw0eaRcOXtdrvVuHANyj8ZErVOr8HlH6op9PSeIUa9TX0m2+tNgKPQvOGseQckA==} cpu: [arm64] os: [linux] libc: [musl] - '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.198': - resolution: {integrity: sha512-qmz8dxEtDIlKntU5qYe0R4aWTxTue5S7zIQknatLX7aJ6HN/nq1aCNXWn5smTH2FViBkUPPR+sCIsNwSk6AT6Q==} + '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.201': + resolution: {integrity: sha512-mShTo3MwF0gkN4dDw78wWJiB6aBDVRkl81cnApvoBofpdyUBYgm9Gw16CCjDTgelMKeBFqN6ErJpwjI3wbP00A==} cpu: [arm64] os: [linux] libc: [glibc] - '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.198': - resolution: {integrity: sha512-h1SrWVIMjLInYNPlf+TxXuKTOdoiOfJLBSoQG97315Z2Nh0IpBfqWExlqYTtPCgKE7q2iga31U283QfHpIDlSQ==} + '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.201': + resolution: {integrity: sha512-IbxnzO5UCbqbm2TnzCHkSyJorAFw2isdKdIsFCTxJJjSs3ZC+v3LC1QSUiVCx0qi+CV6w3MKx6mLI11mrvhbbQ==} cpu: [x64] os: [linux] libc: [musl] - '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.198': - resolution: {integrity: sha512-Zqxyz2AT1UM5WlOOoLJhLssZDgZo8rBK5ku6daveK12zp+UTJGZhGsjFghz1/ASxH08KqOTbUePNTORnPhHAEQ==} + '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.201': + resolution: {integrity: sha512-jrJBrRWrSuoFKIgjyqxHqmfd6Pb3Bs5Bvakg0knXCTC4fbUXGnC9Q6u7gdDwgXohUNP6/DD+s8U7bivvvVv0dg==} cpu: [x64] os: [linux] libc: [glibc] - '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.198': - resolution: {integrity: sha512-mjIHf1HFiRuXefewWTaNZFlTZlCaEt/xsRjc1nSTCEEpFolZayVhrDKz+O2QFVcDtPl8x8GeYSL0kiikg1DZjQ==} + '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.201': + resolution: {integrity: sha512-UsoytRJ/037uHpb3ATrIoe+AgwTf+PwKuFLGjddHAV/11wERJs0hlrnSmcnp43kf0PFxoSNinngme96YYASmQg==} cpu: [arm64] os: [win32] - '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.198': - resolution: {integrity: sha512-y3HLuCCz1kDwUrhd6OnqO+d5BUpTFSzNUsPT9kf3r1vk9HYKF+eMC9eIlcOhiW2kX491kxEvuEOfqgIkGx15cg==} + '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.201': + resolution: {integrity: sha512-PhalN/0cWcqDfbx7iwoLNR2gurjTiqhBk1G6K+NRScxEcQjWuu5xKXCcdbX8ePVpT+nbEMmFEFpn2y+8V8hIdA==} cpu: [x64] os: [win32] - '@anthropic-ai/claude-agent-sdk@0.3.198': - resolution: {integrity: sha512-xt469sSCyclTPtzpLAg0Aschy665GiRMgZKabSmESbGUA5/H56HcILVOiFxclXswkeMUk2fQxfHJUY9UZfiTnA==} + '@anthropic-ai/claude-agent-sdk@0.3.201': + resolution: {integrity: sha512-InT1XLmf2QpldWdtznKDWEoGJT4p+sXh24yxbeBQ++lMJCzMrI0W27MEmmmDWx0otpa+ubdHCF5YQ6oiNt7cmg==} engines: {node: '>=18.0.0'} peerDependencies: '@anthropic-ai/sdk': '>=0.93.0' @@ -191,133 +194,68 @@ packages: zod: optional: true - '@aws-crypto/crc32@5.2.0': - resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} - engines: {node: '>=16.0.0'} - - '@aws-crypto/sha256-browser@5.2.0': - resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} - - '@aws-crypto/sha256-js@5.2.0': - resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} - engines: {node: '>=16.0.0'} - - '@aws-crypto/supports-web-crypto@5.2.0': - resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} - - '@aws-crypto/util@5.2.0': - resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - - '@aws-sdk/client-cognito-identity-provider@3.1045.0': - resolution: {integrity: sha512-oc2nj9g24X6MEL+7ys46g2cNpdnRaL9vggOHtFSigX7WPRfQ3opzUnUYd25q+vy5kRcInCdChcWO4wGEK3XfHg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/core@3.974.8': - resolution: {integrity: sha512-njR2qoG6ZuB0kvAS2FyICsFZJ6gmCcf2X/7JcD14sUvGDm26wiZ5BrA6LOiUxKFEF+IVe7kdroxyE00YlkiYsw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-env@3.972.34': - resolution: {integrity: sha512-XT0jtf8Fw9JE6ppsQeoNnZRiG+jqRixMT1v1ZR17G60UvVdsQmTG8nbEyHuEPfMxDXEhfdARaM/XiEhca4lGHQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-http@3.972.36': - resolution: {integrity: sha512-DPoGWfy7J7RKxvbf5kOKIGQkD2ek3dbKgzKIGrnLuvZBz5myU+Im/H6pmc14QcnFbqHMqxvtWSgRDSJW3qXLQg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-ini@3.972.38': - resolution: {integrity: sha512-oDzUBu2MGJFgoar05sPMCwSrhw44ASyccrHzj66vO69OZqi7I6hZZxXfuPLC8OCzW7C+sU+bI73XHij41yekgQ==} + '@aws-sdk/client-cognito-identity-provider@3.1079.0': + resolution: {integrity: sha512-EISFwFAkHGPard4hsPxD+dGYoJFoGpWF2woa2meF0Gs6LiZ4RTeFsxDTQ0mGokBxHxt+iZ1bIlmA6zZlSDOdiQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.38': - resolution: {integrity: sha512-g1NosS8qe4OF++G2UFCM5ovSkgipC7YYor5KCWatG0UoMSO5YFj9C8muePlyVmOBV/WTI16Jo3/s1NUo/o1Bww==} + '@aws-sdk/core@3.974.27': + resolution: {integrity: sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.39': - resolution: {integrity: sha512-HEswDQyxUtadoZ/bJsPPENHg7R0Lzym5LuMksJeHvqhCOpP+rtkDLKI4/ZChH4w3cf5kG8n6bZuI8PzajoiqMg==} + '@aws-sdk/credential-provider-env@3.972.53': + resolution: {integrity: sha512-+KDA3uc/HZ1vIneGu5QMQb0gAXDYrm2vOE60+BJ7lS0YinMQ5i2oV4PR1A16XkF6K1IbSwjEHd1hQIIgMsK48w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.34': - resolution: {integrity: sha512-T3IFs4EVmVi1dVN5RciFnklCANSzvrQd/VuHY9ThHSQmYkTogjcGkoJEr+oNUPQZnso52183088NqysMPji1/Q==} + '@aws-sdk/credential-provider-http@3.972.55': + resolution: {integrity: sha512-1gBfkWY3RWeBlCoB9lIJjXMx45/54wxcgfzv6BY9otTmMrZPcNPi1v+MwZxxaCUg441NV3jsr1efnFNCXiW70g==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.38': - resolution: {integrity: sha512-5ZxG+t0+3Q3QPh8KEjX6syskhgNf7I0MN7oGioTf6Lm1NTjfP7sIcYGNsthXC2qR8vcD3edNZwCr2ovfSSWuRA==} + '@aws-sdk/credential-provider-ini@3.972.60': + resolution: {integrity: sha512-CV2md+PXvABwRjApWGhQ0wACy9WSFIhnUGrovLcjnjBCd/46TbuivLADtkF8IWNjtCQmQ+2IagSaxqBYqXBNAQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.38': - resolution: {integrity: sha512-lYHFF30DGI20jZcYX8cm6Ns0V7f1dDN6g/MBDLTyD/5iw+bXs3yBr2iAiHDkx4RFU5JgsnZvCHYKiRVPRdmOgw==} + '@aws-sdk/credential-provider-login@3.972.59': + resolution: {integrity: sha512-JG4S9yyA1GFzJdJXqLKrUzZbyK+VDp2QIsJD7YOicJHAhqymfHpDJIok2dLnhOdVB0I37RjdC53uOwCMVS00gw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-host-header@3.972.10': - resolution: {integrity: sha512-IJSsIMeVQ8MMCPbuh1AbltkFhLBLXn7aejzfX5YKT/VLDHn++Dcz8886tXckE+wQssyPUhaXrJhdakO2VilRhg==} + '@aws-sdk/credential-provider-node@3.972.62': + resolution: {integrity: sha512-S6Slq3Tx7bvFk5yc34XNADyZYTX2HUXvaFAnowGRQnhjBO8J/mP62Fn7lxvJwjaDyYm/7gh9h6HEHaltRyMFXw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-logger@3.972.10': - resolution: {integrity: sha512-OOuGvvz1Dm20SjZo5oEBePFqxt5nf8AwkNDSyUHvD9/bfNASmstcYxFAHUowy4n6Io7mWUZ04JURZwSBvyQanQ==} + '@aws-sdk/credential-provider-process@3.972.53': + resolution: {integrity: sha512-EhfH+MQlqOMCkXIVa8MMObPzAQqwTTtxA7KhEJiyPeuNVA8PLOOUpgK7nBrgaDaGiIDLN/9LpGdaHuDjomeRTw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-recursion-detection@3.972.11': - resolution: {integrity: sha512-+zz6f79Kj9V5qFK2P+D8Ehjnw4AhphAlCAsPjUqEcInA9umtSSKMrHbSagEeOIsDNuvVrH98bjRHcyQukTrhaQ==} + '@aws-sdk/credential-provider-sso@3.972.59': + resolution: {integrity: sha512-h8793pOjcImx0SB+VcLONcaQQ57VAvKVuqyewQMRKqqH+CSXsG2dwOeLMUJPMxLdNvL7dXOM0ueTukyNUnu5mA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.37': - resolution: {integrity: sha512-Km7M+i8DrLArVzrid1gfxeGhYHBd3uxvE77g0s5a52zPSVosxzQBnJ0gwWb6NIp/DOk8gsBMhi7V+cpJG0ndTA==} + '@aws-sdk/credential-provider-web-identity@3.972.59': + resolution: {integrity: sha512-VoyO9+vl3XVmpZwn4obskrWIkrA/Jf3lSe1E3ZERlaN9u0D4YZ6+HywC3+L98QOXqZesEfedk67gRER8tK8+8w==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-user-agent@3.972.38': - resolution: {integrity: sha512-iz+B29TXcAZsJpwB+AwG/TTGA5l/VnmMZ2UxtiySOZjI6gCdmviXPwdgzcmuazMy16rXoPY4mYCGe7zdNKfx5A==} + '@aws-sdk/nested-clients@3.997.27': + resolution: {integrity: sha512-A8PIePF9NIIOJ/4Lg1rl9xm/+QaKkHGetq+Z9wb5B+3Da31YYXRo8n7IDMh5C+HQI5eyEmjrwkGWVdYtnLtbXQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.6': - resolution: {integrity: sha512-WBDnqatJl+kGObpfmfSxqnXeYTu3Me8wx8WCtvoxX3pfWrrTv8I4WTMSSs7PZqcRcVh8WeUKMgGFjMG+52SR1w==} + '@aws-sdk/signature-v4-multi-region@3.996.38': + resolution: {integrity: sha512-C379Sk+MiFZCfWZphKlMyLHKxV22OjoGM5KJjj5IJNJcOCWL4IGIpnEGzv1FQiRwhYXfq55SJMfxlqPE08JJ9g==} engines: {node: '>=20.0.0'} - '@aws-sdk/region-config-resolver@3.972.13': - resolution: {integrity: sha512-CvJ2ZIjK/jVD/lbOpowBVElJyC1YxLTIJ13yM0AEo0t2v7swOzGjSA6lJGH+DwZXQhcjUjoYwc8bVYCX5MDr1A==} + '@aws-sdk/token-providers@3.1079.0': + resolution: {integrity: sha512-cbietrLlHPhhmbnMPTuDS4Zj/KNGhY+3vVhn6dwjO6Dqzrwothzg2srtcY34T9mlICsTXn34avDoWLHSntP54A==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.25': - resolution: {integrity: sha512-+CMIt3e1VzlklAECmG+DtP1sV8iKq25FuA0OKpnJ4KA0kxUtd7CgClY7/RU6VzJBQwbN4EJ9Ue6plvqx1qGadw==} + '@aws-sdk/types@3.973.15': + resolution: {integrity: sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1041.0': - resolution: {integrity: sha512-Th7kPI6YPtvJUcdznooXJMy+9rQWjmEF81LxaJssngBzuysK4a/x+l8kjm1zb7nYsUPbndnBdUnwng/3PLvtGw==} + '@aws-sdk/xml-builder@3.972.33': + resolution: {integrity: sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A==} engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.973.8': - resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-arn-parser@3.972.3': - resolution: {integrity: sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-endpoints@3.996.8': - resolution: {integrity: sha512-oOZHcRDihk5iEe5V25NVWg45b3qEA8OpHWVdU/XQh8Zj4heVPAJqWvMphQnU7LkufmUo10EpvFPZuQMiFLJK3g==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-locate-window@3.965.5': - resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-user-agent-browser@3.972.10': - resolution: {integrity: sha512-FAzqXvfEssGdSIz8ejatan0bOdx1qefBWKF/gWmVBXIP1HkS7v/wjjaqrAGGKvyihrXTXW00/2/1nTJtxpXz7g==} - - '@aws-sdk/util-user-agent-node@3.973.24': - resolution: {integrity: sha512-ZWwlkjcIp7cEL8ZfTpTAPNkwx25p7xol0xlKoWVVf22+nsjwmLcHYtTPjIV1cSpmB/b6DaK4cb1fSkvCXHgRdw==} - engines: {node: '>=20.0.0'} - peerDependencies: - aws-crt: '>=1.0.0' - peerDependenciesMeta: - aws-crt: - optional: true - - '@aws-sdk/xml-builder@3.972.22': - resolution: {integrity: sha512-PMYKKtJd70IsSG0yHrdAbxBr+ZWBKLvzFZfD3/urxgf6hXVMzuU5M+3MJ5G67RpOmLBu1fAUN65SbWuKUCOlAA==} - engines: {node: '>=20.0.0'} - - '@aws/lambda-invoke-store@0.2.4': - resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} + '@aws/lambda-invoke-store@0.3.0': + resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} engines: {node: '>=18.0.0'} '@babel/helper-string-parser@7.29.7': @@ -333,8 +271,8 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/runtime@7.28.6': - resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} '@babel/types@7.29.7': @@ -345,28 +283,26 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} - '@bundled-es-modules/cookie@2.0.1': - resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==} - - '@bundled-es-modules/statuses@1.0.1': - resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} - - '@bundled-es-modules/tough-cookie@0.1.6': - resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==} - '@clack/core@1.4.2': resolution: {integrity: sha512-0Ty/1Gfm+Kb07sXcuESjyKfwEhSy4Ns1AgeEisHb/bDY5fWme0tTeTkU14T1Gmcs17YIjB/teiDe4uaCghbYqQ==} engines: {node: '>= 20.12.0'} + '@clack/core@1.4.3': + resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==} + engines: {node: '>= 20.12.0'} + '@clack/prompts@1.6.0': resolution: {integrity: sha512-EYlRokl8szrP9Z25qT5aepMdBjzBvHF9ZEhzIiUBc9guz/T31EqRgvD0QSgZcpE93xiwrr+OkB4nz0BZyF6fSA==} engines: {node: '>= 20.12.0'} - '@esbuild/aix-ppc64@0.27.7': - resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} '@esbuild/aix-ppc64@0.28.1': resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} @@ -374,300 +310,150 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.27.7': - resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.28.1': resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.27.7': - resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.28.1': resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.27.7': - resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.28.1': resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.7': - resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.28.1': resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.27.7': - resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.28.1': resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.27.7': - resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.28.1': resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.7': - resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.28.1': resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.27.7': - resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.28.1': resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.27.7': - resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.28.1': resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.27.7': - resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.28.1': resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.27.7': - resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.28.1': resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.27.7': - resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.28.1': resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.27.7': - resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.28.1': resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.27.7': - resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.28.1': resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.27.7': - resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.28.1': resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.27.7': - resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.28.1': resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.27.7': - resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.28.1': resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.7': - resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.28.1': resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.27.7': - resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.28.1': resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.7': - resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.28.1': resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.27.7': - resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/openharmony-arm64@0.28.1': resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.27.7': - resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.28.1': resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.27.7': - resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.28.1': resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.27.7': - resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.28.1': resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.27.7': - resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.28.1': resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} engines: {node: '>=18'} @@ -680,41 +466,6 @@ packages: peerDependencies: hono: ^4 - '@inquirer/ansi@1.0.2': - resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} - engines: {node: '>=18'} - - '@inquirer/confirm@5.1.21': - resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/core@10.3.2': - resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/figures@1.0.15': - resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} - engines: {node: '>=18'} - - '@inquirer/type@3.0.10': - resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -735,10 +486,6 @@ packages: '@cfworker/json-schema': optional: true - '@mswjs/interceptors@0.39.8': - resolution: {integrity: sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA==} - engines: {node: '>=18'} - '@napi-rs/keyring-darwin-arm64@1.3.0': resolution: {integrity: sha512-pl76hJvdYUBn6I24bXiOBMA9nbDapo3I5B+f3OorjDU4dUMSypXeKbOVehJe8fhgTiH24flMyTS3aAIy43xegQ==} engines: {node: '>= 10'} @@ -820,8 +567,14 @@ packages: resolution: {integrity: sha512-WrOw/bcXm0f9qHkumlT1QlArXSTWqaY9sunsDpOk+yCCorCKMxvWT/a3xko4EYHVdeZoh00yI2TydXn6eyICDA==} engines: {node: '>= 10'} - '@nodable/entities@2.1.0': - resolution: {integrity: sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@nodable/entities@2.2.0': + resolution: {integrity: sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -835,18 +588,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@open-draft/deferred-promise@2.2.0': - resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} - - '@open-draft/logger@0.3.0': - resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} - - '@open-draft/until@2.1.0': - resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - - '@opentelemetry/api@1.9.0': - resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} - engines: {node: '>=8.0.0'} + '@oxc-project/types@0.138.0': + resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} '@oxfmt/binding-android-arm-eabi@0.56.0': resolution: {integrity: sha512-CSCxi7ovYojgfdPOdUb9T508HKeAdDIKeRGg7x8IZwVJrWz9gVgX7MbUnFqtQAE4QvoNo07mj2JlwnOzJw4qqA==} @@ -970,124 +713,124 @@ packages: cpu: [x64] os: [win32] - '@oxlint/binding-android-arm-eabi@1.71.0': - resolution: {integrity: sha512-ImGmd1njEg4FEJH03jhRnveEegtO3czCtfptvaHivKAZQIYATbVFBrrzbaYMYv0oJioTnxZAZVSyV+oL7W8S2g==} + '@oxlint/binding-android-arm-eabi@1.72.0': + resolution: {integrity: sha512-zhCmvn+1Mj3UchAc/90i99S0t7jJUsHmFVSPg4UWrjO8b8eaSGwscgO6QAUtvHBstkjQwBttQNswEnAF1mIQdA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxlint/binding-android-arm64@1.71.0': - resolution: {integrity: sha512-4A5BEexBrwY1YFF8Kiq/lp/wQPRG79G3BWIE1FuWaM5MvmpYSd+7ZySVcKkHdwo0UDzdQGddp6pD9mpctMqLnw==} + '@oxlint/binding-android-arm64@1.72.0': + resolution: {integrity: sha512-mtH+aY/ozv1eZoCUC2owjFAtyNBKHpJHygKeEu9zXXnQGW1Q2/qOpvx+I+Lf23+TvTz66F4iiXUbl2cGvoLPCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxlint/binding-darwin-arm64@1.71.0': - resolution: {integrity: sha512-9wJA9GJulLwS2usU3CEisI/ESDO1n1z9eyTCvApMDrAkbJ1ve0mORgTMjcWWsKxkzkeZ2N/Gpra5IQE7x8tYgQ==} + '@oxlint/binding-darwin-arm64@1.72.0': + resolution: {integrity: sha512-EvnajNPDtfknB3ZieeOOyDTwJn9QXDiwfnF4ZDQqART6RG6hjY4WigQcZdGoK2dkB3e1vrmEzN9aYbQCUkh/gQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxlint/binding-darwin-x64@1.71.0': - resolution: {integrity: sha512-PlLCjS06V0PeJMAJwzjrExw1sYNW9Gch3JtNlcwwZDXGlTYDuwHNN89zYH8LTXFfgkVtsYvs2nv0FqrzyuFDzg==} + '@oxlint/binding-darwin-x64@1.72.0': + resolution: {integrity: sha512-ZkCdEa/G80A7vEHfeCDz/+L3m33DE73v32mDKhgOIgz8Uwf0DFcK7+uu6qC+7LEhmz5fpOe1osWKyjSNMydFIQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxlint/binding-freebsd-x64@1.71.0': - resolution: {integrity: sha512-Lhil7bWre0ncxbUoDoxfS0JzpTz17BRQKW7iwoAUY8GJ66+WwJEfYPCFJ1P0WgVZR5/O/b3Q2pENlHOjeXLOGQ==} + '@oxlint/binding-freebsd-x64@1.72.0': + resolution: {integrity: sha512-NroXv2vh+sxVY1uya/rM5pjhx1hm8BzlYpx9q67QP0Xhw5MH2bf5GJylpvLEC+781p1Xli/317EoV9AlGwViag==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxlint/binding-linux-arm-gnueabihf@1.71.0': - resolution: {integrity: sha512-Oo9/L58PYD3RC0x05d2upAPLllHytTjHQGsnC06P6Ynn7jKkp5mdImQxXdJ3+FnBaKspNpGogzgVsi6g872LiA==} + '@oxlint/binding-linux-arm-gnueabihf@1.72.0': + resolution: {integrity: sha512-0NDywYgfj279Ou/BcQuCYSj7NJwBfmWn5qc5uGO/Ny7fUWmXyIpvawqX/8acQlWG6IXelJsJhj+JAy6sjsKj0A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.71.0': - resolution: {integrity: sha512-mSHfyfgJrEbyIR29ejaeS50BdPk+GoNPlC1dckpDiUZbJAIel68sjSMdOt4WY0/gva+ECC7FNITQkxMJU+vSBw==} + '@oxlint/binding-linux-arm-musleabihf@1.72.0': + resolution: {integrity: sha512-4vpXB06h65Ezsy4hRyrGjGrfa1SkVPii09yaajiYhmVpgsFiLD+KNxIx/BNAY+XiO+i1yqp9HHdwqM8VTqa5XQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm64-gnu@1.71.0': - resolution: {integrity: sha512-n9yY4M2tiy3aij4AqtlnspzpfdpeT5JQfK2/w2d8oyp5W0FRwOb1dIeX99nORNcxGr08iD9bH8N5XFz3I2iy8w==} + '@oxlint/binding-linux-arm64-gnu@1.72.0': + resolution: {integrity: sha512-immaN4g2ZGFiOkKrvRX9LvzZdd2GkQM5wR+UyzYyUuyhUTXGQ4HKUJH18xp4G8OfhCVaVAJfKZxwE1r8+4hhaQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-arm64-musl@1.71.0': - resolution: {integrity: sha512-fJZrs5sDZtTaPIOiemRQQmo82Ezy+vOGXemPc4Ok7iVVsYsFa7SlW6Z5XN819VfsqBHRm3NJ3rTdnR8+bJYJdQ==} + '@oxlint/binding-linux-arm64-musl@1.72.0': + resolution: {integrity: sha512-JGHS9Mnr7iWyyLDxgCv1MhzVpAckgptg00F2gnxt/GD7lQ2SW1BRcxHqhSTaSdDpjWRrBkBxMMh4+Hn3aVtExg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxlint/binding-linux-ppc64-gnu@1.71.0': - resolution: {integrity: sha512-cwl7VKGERIy9p+G+AvZdfy/06q0aHXaTt/mMRReC751iuNYJgqKjB7NydXSS30nBT9vtr2tunciOtrR4fD6FUA==} + '@oxlint/binding-linux-ppc64-gnu@1.72.0': + resolution: {integrity: sha512-AOYgBZqxNshrg83P9v0RYv+m8s10Cqkj4/PxXFDhcS3k7FqsIG5+CxErshZCIN7G8iy4Y+VGfAsuEdar8AcbBg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-gnu@1.71.0': - resolution: {integrity: sha512-eZ8ieVXvzGi8jr7+ybQGPK2STw3mldfxZlgA2738iflfB/rzA69sE6m5rDRpQaxC7dpm745Enlh1Tod0QAk9Gg==} + '@oxlint/binding-linux-riscv64-gnu@1.72.0': + resolution: {integrity: sha512-QMybPS5ij3/vrKG67mqzHwW++91sYxK/PPUVi6SBtNCEzW4niS52fVBdXbQ6nou0wWbUPEpx8Sl/ZjtgE3clXA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-musl@1.71.0': - resolution: {integrity: sha512-puMDbQYe6+NXwfMusojoA7CXGn2b3utukmd23PQqc1E3XhVCwyZ+FueSMzDYeNgDV2dUfIVXAAKZBcFDeCL6sA==} + '@oxlint/binding-linux-riscv64-musl@1.72.0': + resolution: {integrity: sha512-gOc3W7JV0PXRpIL7stUlLe3Wa9Gp0Kdlup87IT3gHDvPKck2xNgMIl/Gs2lldYY2lyXZDC4rWi3hmoLUobkgbQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxlint/binding-linux-s390x-gnu@1.71.0': - resolution: {integrity: sha512-4NJLxBs1ujISCt3L/1FcywLs73PWtJuw+piD6feK2V6h6OS6P7xu9/sWt1DTRLibe6QCzmfZzmM/2HPORoV/Lg==} + '@oxlint/binding-linux-s390x-gnu@1.72.0': + resolution: {integrity: sha512-rpGxph+FjjHcYI5q6uxB3Az+tnfmEnDbSA8+PK9ZE/VzyUAkvBOMeuY7ZQMhu5mpZH7YQDsTdW6Cx4kV/msc6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-gnu@1.71.0': - resolution: {integrity: sha512-cFDaiR8L3430qp88tfZnvFlt3KotFhR/DlbIL0nHOMMYiG/9Wy4l+6f7t8G8pTa9bd8Lt8+M0y/qjRQ/xcB74g==} + '@oxlint/binding-linux-x64-gnu@1.72.0': + resolution: {integrity: sha512-WND+uhf/Ko13SLqQMWQUgsZuLvYYEvL0ZKgg0tgGYfLqxG7l8Ju123fHDMJyYSDl5E3bUbpFUuii/OvMreFQzw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-musl@1.71.0': - resolution: {integrity: sha512-orfixdt76KlpNly9z0PkWBBNfwjKz+JFVLP/7wnVchlKNU9Dpt9InU/ZggeSej6fC7qwHmHNOGlhLnQXcYoGuA==} + '@oxlint/binding-linux-x64-musl@1.72.0': + resolution: {integrity: sha512-SrpbrUL70nG9vh6zP4/oKHWgLuHquwsr7MW9XOn0olBVgh10Uqr8qscKhQoBGEn6olK/IUpn5GSKcdQ5AjUhGA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxlint/binding-openharmony-arm64@1.71.0': - resolution: {integrity: sha512-9emQu2lAp6yhPB3XuI+++vR+l/o6JR1X+EpxwcumPdQXBWXEPAsquPGL7l158EqU8SebQMXTUa/S5zN98juyHw==} + '@oxlint/binding-openharmony-arm64@1.72.0': + resolution: {integrity: sha512-qkrsEn6NmgFKr7U/QnezQMb+q/vzAy0Dd9Y95gQGQTyjzDLN+HRZMuM5u70iyH4nBLCfKBzhjMsYCehKay2jyg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxlint/binding-win32-arm64-msvc@1.71.0': - resolution: {integrity: sha512-bd5kI8spYwTm3BILDtGhi73zoup5dw8MlPQNT8YB3BD5UIsjNe3K9/4ctrzQMX4SZMoK5HgzVLkLJzacEXB7fA==} + '@oxlint/binding-win32-arm64-msvc@1.72.0': + resolution: {integrity: sha512-LWR6ZlFZph+KPjXv8opgZsXRDCdrdQe8VL8Cg9zxCoBS73h6znzZpydVgmdnwj8mB9AuSM5jxEgDJDpQkjboeg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.71.0': - resolution: {integrity: sha512-W4HvOHGzVLHcrmFu+bMrJlho+/yrlX5ZNdJZqGe8MEldkQG+RHYhxxad9P4jvWAYFmIqUA5i9DQ8QsJqSU9GIw==} + '@oxlint/binding-win32-ia32-msvc@1.72.0': + resolution: {integrity: sha512-yt6HEh7IsHvtjRWtmeZRX134eaXKHq5Gnqlf1xBJdJl1JtdoRUEJw3nAxpZoUDS860cX/foKbztO441anVBtVQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxlint/binding-win32-x64-msvc@1.71.0': - resolution: {integrity: sha512-D2kyEIPHk/G/wiZLnwTVC/sVst+T/lKldVOjAFpgTIBUAOlry72e5OiapDbDBF4LfJLkN5ypJb/8Eu6yJzkveQ==} + '@oxlint/binding-win32-x64-msvc@1.72.0': + resolution: {integrity: sha512-b2eKFD2hX7tIwmo/cyH6TDq8vzWRZ2qNHrzoGntUTmq0h3zQh/uX3eTSHCwI8OB/ADQfJCRelLItK8BsxuucDA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -1101,286 +844,133 @@ packages: '@redocly/ajv@8.18.3': resolution: {integrity: sha512-l42u0of3hY98sN2A+M4qTX1O/KrpgGH32Hu9kP2GtHyD5Dfqq86PKFLe5dwaD8DEnNmlOlll2BAmeEtf0DaySg==} - '@redocly/config@0.49.1': - resolution: {integrity: sha512-Eid8/bDcsf2bpTJ2qZhULflf6Y/TtoUFZt0+a5XZzjZj0uA8L8EQiY/nEdBd6lZQlZsnu8/cAUhTyBebnLi0gA==} + '@redocly/config@0.50.1': + resolution: {integrity: sha512-TrdZUK50baxIjJB/y2ROOqfg35ex+GbkHPoJ40kXQXKMOjrfxfYQ9IliiaLqT5H/Y8qbajPrYQN2DLfvcMaHSw==} - '@redocly/openapi-core@2.36.0': - resolution: {integrity: sha512-u44e3yn0Zj2d59+SzMrHVj0DQZfQJm8C8uaf4MhJDAiHLHyd7adcAoRiqDD+LzkfLvgBepp20Jo6gDEIGl1mDg==} + '@redocly/openapi-core@2.37.0': + resolution: {integrity: sha512-i+q5+3ciI+KjMpcPsec1XO7V3l83g/aX1kZRmuPhJQilKMY2cBDl9M3O9r8httDK9v+V19mF3iIGcjxlJcUlrg==} engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'} - '@rollup/rollup-android-arm-eabi@4.62.2': - resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.62.2': - resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + '@rolldown/binding-android-arm64@1.1.4': + resolution: {integrity: sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.62.2': - resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + '@rolldown/binding-darwin-arm64@1.1.4': + resolution: {integrity: sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.62.2': - resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + '@rolldown/binding-darwin-x64@1.1.4': + resolution: {integrity: sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.62.2': - resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.62.2': - resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + '@rolldown/binding-freebsd-x64@1.1.4': + resolution: {integrity: sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': + resolution: {integrity: sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.62.2': - resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + '@rolldown/binding-linux-arm64-gnu@1.1.4': + resolution: {integrity: sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.62.2': - resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + '@rolldown/binding-linux-arm64-musl@1.1.4': + resolution: {integrity: sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.62.2': - resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.62.2': - resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.62.2': - resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + '@rolldown/binding-linux-ppc64-gnu@1.1.4': + resolution: {integrity: sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.62.2': - resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.62.2': - resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.62.2': - resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.62.2': - resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + '@rolldown/binding-linux-s390x-gnu@1.1.4': + resolution: {integrity: sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.62.2': - resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + '@rolldown/binding-linux-x64-gnu@1.1.4': + resolution: {integrity: sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.62.2': - resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + '@rolldown/binding-linux-x64-musl@1.1.4': + resolution: {integrity: sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.62.2': - resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.62.2': - resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + '@rolldown/binding-openharmony-arm64@1.1.4': + resolution: {integrity: sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.62.2': - resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.62.2': - resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} - cpu: [ia32] - os: [win32] + '@rolldown/binding-wasm32-wasi@1.1.4': + resolution: {integrity: sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] - '@rollup/rollup-win32-x64-gnu@4.62.2': - resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} - cpu: [x64] + '@rolldown/binding-win32-arm64-msvc@1.1.4': + resolution: {integrity: sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.62.2': - resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + '@rolldown/binding-win32-x64-msvc@1.1.4': + resolution: {integrity: sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@smithy/config-resolver@4.5.1': - resolution: {integrity: sha512-abXk3LhODsvRHsk0ZS9ztrg/fZatTa9Z/z4pgx65YSLR+rY6kvUG/1IgcDKEUciR8MfdnkT5oPeHJTy/HhzDIQ==} - engines: {node: '>=18.0.0'} - - '@smithy/core@3.24.1': - resolution: {integrity: sha512-3mT7o4qQyUWttYnVK3A0Z/u3Xha3E81tXn32Tz6vjZiUXhBrkEivpw1hBYfh84iFF9CSzkBU9Y1DJ3Q6RQ231g==} - engines: {node: '>=18.0.0'} - deprecated: Deprecated due to bug in browser bundling instructions https://github.com/smithy-lang/smithy-typescript/issues/2025 - - '@smithy/credential-provider-imds@4.3.1': - resolution: {integrity: sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ==} - engines: {node: '>=18.0.0'} - - '@smithy/fetch-http-handler@5.4.1': - resolution: {integrity: sha512-r7bN6spQ+caZC8AnyvSxkRUb57zt2jhhRw3Z+2Ez8hjq6coIikDBFUUI/+CQ1xx9K6eX1Gx6wUKo4ylU66TIqw==} - engines: {node: '>=18.0.0'} - - '@smithy/hash-node@4.3.1': - resolution: {integrity: sha512-u0/zo11mg7yNneoYgTkH4sXwSmcBpbl49o4UNCtQ7hYsXxynsN25KYHmXzqi7TPk5HQL5klGnpU5koOY0O+9hw==} - engines: {node: '>=18.0.0'} - - '@smithy/invalid-dependency@4.3.1': - resolution: {integrity: sha512-cLmwtDoulyZvRepAfyV+3rx5oMvuh51dbE+6En3vGC09j3uVSRt1U4oguNu32ub3soGX0oYtBs8E7S2Q4SxTqg==} - engines: {node: '>=18.0.0'} - - '@smithy/is-array-buffer@2.2.0': - resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} - engines: {node: '>=14.0.0'} - - '@smithy/middleware-content-length@4.3.1': - resolution: {integrity: sha512-l4BUIP+wljW/Ar+0/QcGdmElI9lalrywfzNijXMBG34Z510FRzPyrDLx/blNTZOAm0C4Mvx5t/bf760CZo1ajg==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-endpoint@4.5.1': - resolution: {integrity: sha512-qtqu5TS+8Y18ZDkJoiXN5AMW1G4JAg1+xytzpsUvIR5a4EUsgd5HQg12lekEHWpm2TDUmOgg+hBaHK7dvyWdkA==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-retry@4.6.1': - resolution: {integrity: sha512-eTaQhxs0rfUuAkL2MSKrH8DTO7YCeAgrdN0B2/RAeuHmXQ+x52dk5qUBsi/jtcqe5LxItgq5AG5tI6Cp8c0sow==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-serde@4.3.1': - resolution: {integrity: sha512-t7YtUe076zWVypVmy1rX91oKi2TFJCkpfFpfMhJFpEIRPP0iL9JxjeSyFQ+1bF45JUfDzOzslUJa150WcSrBug==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-stack@4.3.1': - resolution: {integrity: sha512-1jKwiKZxCMQNqmp4uVPYA6r+MLGjEtH07gnOUdPgbnjuOIrl/0JY/ICdpQtFgeBsQ/Up01gnSv8GYEL0fb8yvg==} - engines: {node: '>=18.0.0'} - - '@smithy/node-config-provider@4.4.1': - resolution: {integrity: sha512-q7tDJEJXcaSG/8TVpu2f2l9bzxTzDM9geWmltbzsY6Hfh3yiuXXTpLIO8+zwYASPPVFaTJpdKwjSSjdoDoccgw==} - engines: {node: '>=18.0.0'} - - '@smithy/node-http-handler@4.7.1': - resolution: {integrity: sha512-BdEYko85f/ldp68uH8XEyIvo810xFk6eyPH81SRggTOApYHWA+Xu7B2EzLuHbe37WVLaUA7F1fWR3/zBeme2WA==} - engines: {node: '>=18.0.0'} - - '@smithy/property-provider@4.3.1': - resolution: {integrity: sha512-3NHoqVBhzpY2b4YBx9AqyKC4C8nnEjl5FyKuxrCjvnjinG0ODj+yg1xX360nNahT6wghYjSw1SooCt3kIdnqIA==} - engines: {node: '>=18.0.0'} - - '@smithy/protocol-http@5.4.1': - resolution: {integrity: sha512-8irPNCQgYxcSFp1aGcnDNFkTwSA+xPUaFq9V/v1+JXWu8sKr5b3cFmg2kBTkjkvypDmGeNffuNu0x5iqw1NoAw==} - engines: {node: '>=18.0.0'} - - '@smithy/shared-ini-file-loader@4.5.1': - resolution: {integrity: sha512-FKoKxVzdFPhyynFI+SPTWrgOP60fZ4l1UwukWYj4eyhpSmEI7MJ6p58hawIIt9bwp+aek9NEm8Zika7E+GEoeg==} - engines: {node: '>=18.0.0'} - - '@smithy/signature-v4@5.4.1': - resolution: {integrity: sha512-728lZZEWYWubBESrfntNslZQYDKRlJDY4dcDnYbL50+gu35pGPLblu4S0/RH/RDLF6me1M87ECHsHELGL7dA/Q==} - engines: {node: '>=18.0.0'} - - '@smithy/smithy-client@4.13.1': - resolution: {integrity: sha512-IcznNM8Qd9u1X3oflp12tkzyOB4HbT+sfYWlWiyEysgNzSHoWcHUUsTT4y1jjDjtVuuVVQbYks+g1kVd7u1eGQ==} - engines: {node: '>=18.0.0'} - - '@smithy/types@4.14.1': - resolution: {integrity: sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==} - engines: {node: '>=18.0.0'} - - '@smithy/url-parser@4.3.1': - resolution: {integrity: sha512-tuelFlF2PZR/wogFC58NIrPOv+Zna4N1+3kA161/33D1Gbwvl6Nh4WsAsW05ZyPp0O6CMGsdbb0S2b/qVjRMCw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-base64@4.4.1': - resolution: {integrity: sha512-fTHiwW2xbiRiWzfSk4IGAr3gNZCH4fuRYqt8+IuarsP/YON35576iVdePraZ6yJlFxlCL0eMec3/F7xYqoKzlg==} - engines: {node: '>=18.0.0'} - - '@smithy/util-body-length-browser@4.3.1': - resolution: {integrity: sha512-1scg5t4nV3hV7CZs996/XHb80aDZ5YotH4NcvkW/w/rHj+cSz0aCIzwz8aUNKB4nCDPSHRCbrKoj+TvycYefmw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-body-length-node@4.3.1': - resolution: {integrity: sha512-VRC8MKVPKrgUYThTA7ughcKMfjW6/X92H0wXGJoda0Apw4O5xbXL0GMLz40DTWlsb5hh2iItk6+XL72uJdxYcw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-buffer-from@2.2.0': - resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} - engines: {node: '>=14.0.0'} - - '@smithy/util-config-provider@4.3.1': - resolution: {integrity: sha512-lw6L5GF5+W19vO6o3fZwRT2cXEG+8b2LH0b9ppjDT6nIxjUgmljEQGninx5XorylwKZZ4XLVABeroJ8oaF9RmQ==} - engines: {node: '>=18.0.0'} + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@smithy/util-defaults-mode-browser@4.4.1': - resolution: {integrity: sha512-1rA7w+LjK1WJClsffC81Z/ZtjFt22QsKhBjUYEnZsGVS2nOTfOENKBzdg4SxhdwFvBCjcbpjscUfXOPwE3UHWQ==} + '@smithy/core@3.29.1': + resolution: {integrity: sha512-qoiY4nrk5OCu1+eIR1VB8l5DmON/oKiqrd5zZFAhXJXjJlLWQusKEW/SkBDAtGDcPaz86m9kfcE1lngU0GlM6A==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.3.1': - resolution: {integrity: sha512-1fk1wfQHBenQD5NitVKOFgW0wsISYAFPIXGyStJWAeCtMyRhgHYvtJxBk2rwGWA0L5QX6oM6yeHSLKPFMk59ww==} + '@smithy/credential-provider-imds@4.4.6': + resolution: {integrity: sha512-B2WQ/PV/H6Jeg3lrIq6bKUfa6Hy01mtK7CGs6lhjzHA6k4aagldH6T6eEjnzKl4HI0cJnAsxfJ19pgb5PV+CVQ==} engines: {node: '>=18.0.0'} - '@smithy/util-endpoints@3.5.1': - resolution: {integrity: sha512-yORYzJD5zoGbSDkAACr0dIjDiSEA3X8h8lggDENl1dkKpCG0TQIoItPBqtvuJHzFFjRXumcoH+/09xIuixGyCw==} + '@smithy/fetch-http-handler@5.6.3': + resolution: {integrity: sha512-CwCc/7SMTj45y97MUnDTbTaxvtAsiNNRm81z3abROIuMbMsC2Iy5EKfkkVdsKrz8WExQAAMx1EJapq+9j4fFTQ==} engines: {node: '>=18.0.0'} - '@smithy/util-middleware@4.3.1': - resolution: {integrity: sha512-SRRMDcIgVXVhVbxviBaSZbuWuVW3jD08wv4ESV0V2oiw0Mki8TPVQ5IxwD3MvSTPg52QYsRP+JoMw5WdUdeWAg==} + '@smithy/node-http-handler@4.9.3': + resolution: {integrity: sha512-qZTa4gQFUo8RM02rk6q5UVTDLNrQ1oS20LsepBzqq1QBVc/EHJ03OOUADcqMZiXHArW+Y7+OGY0BpdTwZRq/Yg==} engines: {node: '>=18.0.0'} - '@smithy/util-retry@4.4.1': - resolution: {integrity: sha512-qkgWgwn1xw0GoY9Ea/B6FrYSPfHA0zyOtJkokwxZuvucRf2+2lfTut6adi4e4Y7LEAaxsFG7r6i05mtDCxbHKA==} + '@smithy/signature-v4@5.6.2': + resolution: {integrity: sha512-QgHflghMoPxCJ9axiCVh8KZfbC9fuP6vkXXyK//E3cq7nLaSSyyLj0GAoqVWezYeDQmXIZhmlRvLE16jsqDK6g==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.6.1': - resolution: {integrity: sha512-GjZfEft0M0V3n2YM/LGkr5LeLd8gxHUIzW0rUz6VtTtlAq245GxHlJghvoPEjJHKTj255iHFAiA4IsIdK40Ueg==} - engines: {node: '>=18.0.0'} - - '@smithy/util-utf8@2.3.0': - resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} - engines: {node: '>=14.0.0'} - - '@smithy/util-utf8@4.3.1': - resolution: {integrity: sha512-FtRrSnriXtOs4+J8/y9SbQ1xmN71hrOsN/YJr5PQQj5nR1l7YNkGS/TEk4gr0WN7gyrUqw8/RFaYVjI18732ZA==} + '@smithy/types@4.15.1': + resolution: {integrity: sha512-x3L0XSACF6UYzKpa9biqiRMgvH5+wnFFew9Tm/grFYqgaupPwx/+ojDPpPJM8dZON3S9tjz5U+PQYsCBd1Mw5Q==} engines: {node: '>=18.0.0'} '@stablelib/base64@1.0.1': @@ -1394,12 +984,12 @@ packages: peerDependencies: xstate: ^5.5.1 + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - '@types/cookie@0.6.0': - resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} - '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -1422,32 +1012,26 @@ packages: '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} - '@types/statuses@2.0.6': - resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} - - '@types/tough-cookie@4.0.5': - resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@vitest/coverage-v8@4.1.9': - resolution: {integrity: sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g==} + '@vitest/coverage-v8@4.1.10': + resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==} peerDependencies: - '@vitest/browser': 4.1.9 - vitest: 4.1.9 + '@vitest/browser': 4.1.10 + vitest: 4.1.10 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.9': - resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} - '@vitest/mocker@4.1.9': - resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1457,25 +1041,25 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.9': - resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - '@vitest/runner@4.1.9': - resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - '@vitest/snapshot@4.1.9': - resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} - '@vitest/spy@4.1.9': - resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} - '@vitest/ui@4.1.9': - resolution: {integrity: sha512-U/cRvtqfEPj27FI1n9cyUvi4vXXdcLhjJiI+InYKdk8hP4VrS6RXOjGL7rfFaeBc37iRKANsR6eEzIoC7lmgBQ==} + '@vitest/ui@4.1.10': + resolution: {integrity: sha512-EOUqfXHTXtpSHsyLHH40ts3Ue+hRhSGwzwzMlK0dTEOLSDYyOXLyr5JDGmHQWhN2DYI30gw6dVx3cdgM9FZl+Q==} peerDependencies: - vitest: 4.1.9 + vitest: 4.1.10 - '@vitest/utils@4.1.9': - resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} '@workos-inc/node@10.7.0': resolution: {integrity: sha512-rffa9znZuIv4yo+9JRxGOLTTSxh0XhOT6jlsktgqEi9MuB9V0VFHRzLd3bTpkq+J9sgrPZNGpvX4aWNfMqt5cQ==} @@ -1485,8 +1069,8 @@ packages: resolution: {integrity: sha512-NgQKHpwh8AbT4KvAsW91Y+4f4jja2IvFPQ5atcy5NUxUMVRgXzRFEee3erawfXrTmiCVqJjd9PljHySKBXmHKQ==} engines: {node: '>=20.15.0'} - '@workos/migrations@2.4.0': - resolution: {integrity: sha512-SLK2Dps1yzXY1o9sAHIlIXQfd6jmoI9yZuZQSVA4EtNzdi0Vg5L0mRop36tJqp406Y69s/TuO6evqPzcBak94Q==} + '@workos/migrations@2.5.0': + resolution: {integrity: sha512-2kBiKOf0djjQIThpi43POWy76Dkvx8fFtKvdKtMNiOk5rJqyjsX3Y3oU7JjSx+gZJTfW2YfdDXrQhPnWzdyiUw==} engines: {node: '>=22.11.0'} hasBin: true @@ -1528,26 +1112,17 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - ansi-regex@6.2.2: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + anynum@1.0.1: + resolution: {integrity: sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1618,18 +1193,10 @@ packages: resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} engines: {node: '>=4'} - cli-truncate@5.1.1: - resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} engines: {node: '>=20'} - cli-width@4.1.0: - resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} - engines: {node: '>= 12'} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - cliui@9.0.1: resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} engines: {node: '>=20'} @@ -1638,13 +1205,6 @@ packages: resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} @@ -1701,8 +1261,8 @@ packages: csv-parse@6.2.1: resolution: {integrity: sha512-LRLMV+UCyfMokp8Wb411duBf1gaBKJfOfBWU9eHMJ+b+cJYZsNu3AFmjJf3+yPGd59Exz1TsMjaSFyxnYB9+IQ==} - csv-stringify@6.7.0: - resolution: {integrity: sha512-UdtziYp5HuTz7e5j8Nvq+a/3HQo+2/aJZ9xntNTpmRRIg/3YYqDVgiS9fvAhtNbnyfbv2ZBe0bqCHqzhE7FqWQ==} + csv-stringify@6.8.1: + resolution: {integrity: sha512-tZ6X6TKQyQgCo5OptXcyAbfN1pwmoxEqELPQ7KFazNErx7kiVsDK8o+VYRXhfMl4N9vvOOLXuioquR2MeP847A==} data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} @@ -1733,6 +1293,10 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + diff@8.0.4: resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} engines: {node: '>=0.3.1'} @@ -1751,8 +1315,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1773,20 +1337,15 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.2.0: - resolution: {integrity: sha512-3lGxdTXCLfe1MYfTz1y2ksAAUM4NAOP6rPEjxGJVKO7TZ5+tvHCaQWGpC4Y3IXvW3ece0Cz1cIP4FWBxOnGCTQ==} + es-module-lexer@2.3.0: + resolution: {integrity: sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} - es-toolkit@1.44.0: - resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} - - esbuild@0.27.7: - resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} - engines: {node: '>=18'} - hasBin: true + es-toolkit@1.49.0: + resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} @@ -1868,19 +1427,15 @@ packages: fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} - fast-xml-builder@1.2.0: - resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==} - - fast-xml-parser@5.7.2: - resolution: {integrity: sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w==} - hasBin: true + fast-xml-builder@1.2.1: + resolution: {integrity: sha512-tPb5TTWfgfVx5BNSi2xV0eLr89POeXXn0dXIsCJ9m1narrWxeIyx6je9d7Rce/3NyXLbvuQmLkxq+RuxMWejvw==} - fast-xml-parser@5.8.0: - resolution: {integrity: sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==} + fast-xml-parser@5.9.3: + resolution: {integrity: sha512-brCNCeScma/kqa54J4PIDriSSSLssRkuYaUCpvHJulGc3HGI/xxKUCTDcYkAdqJsyb//ydpbxecjC3hB9+tb/g==} hasBin: true - fastq@1.19.0: - resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==} + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} @@ -1929,8 +1484,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - gaxios@7.1.5: - resolution: {integrity: sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==} + gaxios@7.1.6: + resolution: {integrity: sha512-aIQ0QL8Or8vsUhHyXGA6AohOFRrAAiHhrvsAG6myzcSlfhxSXtnwXA/pRuQTilFgjhLe30swK5rg1d7E1f8Izw==} engines: {node: '>=18'} gcp-metadata@8.1.2: @@ -1941,12 +1496,8 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.3.0: - resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} - engines: {node: '>=18'} - - get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} get-intrinsic@1.3.0: @@ -1989,15 +1540,8 @@ packages: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} - headers-polyfill@4.0.3: - resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} - - hono@4.11.4: - resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==} - engines: {node: '>=16.9.0'} - - hono@4.12.27: - resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} + hono@4.12.28: + resolution: {integrity: sha512-YwUvVpSF7m1yOblFPrU3Hbo8XhPheBoiyfGuII6z19LnOr6JpDnyyp7LFNrfV56wS8tpvtBFGRISHN02pDdLOA==} engines: {node: '>=16.9.0'} html-escaper@2.0.2: @@ -2011,8 +1555,8 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - iconv-lite@0.7.2: - resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} indent-string@5.0.0: @@ -2056,10 +1600,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} - engines: {node: '>=18'} - is-fullwidth-code-point@5.1.0: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} @@ -2082,9 +1622,6 @@ packages: engines: {node: '>=14.16'} hasBin: true - is-node-process@1.2.0: - resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -2092,6 +1629,9 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-unsafe@1.0.1: + resolution: {integrity: sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA==} + is-what@4.1.16: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} @@ -2155,6 +1695,9 @@ packages: json-schema-typed@8.0.2: resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jwa@2.0.1: resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} @@ -2165,6 +1708,80 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -2214,20 +1831,6 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msw@2.10.4: - resolution: {integrity: sha512-6R1or/qyele7q3RyPwNuvc0IxO8L8/Aim6Sz5ncXEgcWUNxSKE+udriTOWHtpMwmfkLYlacA2y7TIx4cL5lgHA==} - engines: {node: '>=18'} - hasBin: true - peerDependencies: - typescript: '>= 4.8.x' - peerDependenciesMeta: - typescript: - optional: true - - mute-stream@2.0.0: - resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} - engines: {node: ^18.17.0 || >=20.5.0} - nanoid@3.3.15: resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2289,9 +1892,6 @@ packages: engines: {node: '>=8'} deprecated: The package has been renamed to `open` - outvariant@1.4.3: - resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} - oxfmt@0.56.0: resolution: {integrity: sha512-9Dv0wV3zKiyvhjD7bRKaInKmHQ1sPx3RGOjQkGFJbbdQ16576yf8qhMSO9Q9cvHcs+1NpBsRTkuDDYFFPTJ6gw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2305,8 +1905,8 @@ packages: vite-plus: optional: true - oxlint@1.71.0: - resolution: {integrity: sha512-U1m1X+C0vDj7DC1e13IoZULzEcPczE7UOMTs8VlZGHUEIUaSTZKo5qkPsQEfzpgnQ29Pea/w3Xntk62UCecxZw==} + oxlint@1.72.0: + resolution: {integrity: sha512-1rhdZIP/EvoI91ABIwNU5Q8+bWf8mjrS5UzIOZld4d4bXxJvtlUhlQvaoTogIGin/qdErMOrwaIJvCSIAKTLhA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -2333,17 +1933,14 @@ packages: resolution: {integrity: sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - path-expression-matcher@1.5.0: - resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==} + path-expression-matcher@1.6.1: + resolution: {integrity: sha512-h7bxdzhHk8Knyc4Tj+jMaa7fEEoUJy7p1qtbVgkYg1Uhpe5Np5VuGXCRZnkZvU+Q42M1vStt0ifa3ueykRJPmQ==} engines: {node: '>=14.0.0'} path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-to-regexp@6.3.0: - resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} - path-to-regexp@8.4.2: resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} @@ -2357,8 +1954,8 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} pkce-challenge@5.0.1: @@ -2385,20 +1982,10 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - psl@1.15.0: - resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - qs@6.15.3: resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} engines: {node: '>=0.6'} - querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2420,28 +2007,21 @@ packages: resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} engines: {node: '>=0.10.0'} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - restore-cursor@4.0.0: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.62.2: - resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} + rolldown@1.1.4: + resolution: {integrity: sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true router@2.2.0: @@ -2514,10 +2094,6 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -2525,10 +2101,6 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - slice-ansi@8.0.0: resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} engines: {node: '>=20'} @@ -2554,9 +2126,6 @@ packages: std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} - strict-event-emitter@0.5.1: - resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2565,24 +2134,20 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string-width@8.2.0: - resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + string-width@8.2.1: + resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-ansi@7.2.0: resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} - strnum@2.3.0: - resolution: {integrity: sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==} + strnum@2.4.1: + resolution: {integrity: sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==} superjson@1.13.3: resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==} @@ -2631,10 +2196,6 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} - tough-cookie@4.1.4: - resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} - engines: {node: '>=6'} - tree-sitter-c-sharp@0.23.1: resolution: {integrity: sha512-9zZ4FlcTRWWfRf6f4PgGhG8saPls6qOOt75tDfX7un9vQZJmARjPrAC6yBNCX2T/VKcCjIDbgq0evFaB3iGhQw==} peerDependencies: @@ -2665,7 +2226,7 @@ packages: optional: true tree-sitter-kotlin@https://codeload.github.com/fwcd/tree-sitter-kotlin/tar.gz/f66d2908542e93c0204c6c241f794afe4e9cd5d1: - resolution: {gitHosted: true, tarball: https://codeload.github.com/fwcd/tree-sitter-kotlin/tar.gz/f66d2908542e93c0204c6c241f794afe4e9cd5d1} + resolution: {gitHosted: true, integrity: sha512-7pk1Tg/gXh+6hM4E0F2rPKeLyA/bNlYyqVu6T1Md/AV/vloakbvEZG0R4CYwUfVtgFAMZRbOtA8JBzX1SFatBA==, tarball: https://codeload.github.com/fwcd/tree-sitter-kotlin/tar.gz/f66d2908542e93c0204c6c241f794afe4e9cd5d1} version: 0.4.0 peerDependencies: tree-sitter: ^0.21.1 @@ -2729,17 +2290,13 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.22.4: - resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==} + tsx@4.23.0: + resolution: {integrity: sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==} engines: {node: '>=18.0.0'} hasBin: true - type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} - - type-fest@5.4.4: - resolution: {integrity: sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==} + type-fest@5.8.0: + resolution: {integrity: sha512-YGYEVz3Fm5iy/AybuA0oyNFq7H4CgQNfRp/qfe8nurE1kuCeNm3/vfm9X4Mtl+qLyaKJUh5xrFZwogr41SMjYA==} engines: {node: '>=20'} type-is@2.1.0: @@ -2759,17 +2316,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - universalify@0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - uuid@13.0.2: resolution: {integrity: sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==} hasBin: true @@ -2778,15 +2328,16 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vite@7.3.1: - resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + vite@8.1.3: + resolution: {integrity: sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 - lightningcss: ^1.21.0 sass: ^1.70.0 sass-embedded: ^1.70.0 stylus: '>=0.54.8' @@ -2797,12 +2348,14 @@ packages: peerDependenciesMeta: '@types/node': optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true jiti: optional: true less: optional: true - lightningcss: - optional: true sass: optional: true sass-embedded: @@ -2818,20 +2371,20 @@ packages: yaml: optional: true - vitest@4.1.9: - resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.9 - '@vitest/browser-preview': 4.1.9 - '@vitest/browser-webdriverio': 4.1.9 - '@vitest/coverage-istanbul': 4.1.9 - '@vitest/coverage-v8': 4.1.9 - '@vitest/ui': 4.1.9 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2877,33 +2430,13 @@ packages: resolution: {integrity: sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA==} engines: {node: '>=20'} - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.19.0: - resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.21.0: resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} @@ -2924,8 +2457,8 @@ packages: resolution: {integrity: sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==} engines: {node: '>=16.0.0'} - xstate@5.32.2: - resolution: {integrity: sha512-uDrojEQYYb4cEeB/SpKDBQlnL2969N5ltmVak4jUMUC6VVRuhi7PCnTBxe4YlQ8YLzdaOEOuVR48CRQPE2o0Uw==} + xstate@5.32.4: + resolution: {integrity: sha512-E5WtDB8DBs2ZWliz2Ry9XfbSZTbBRcK/cwefBot04qQ/L5SLP16xpnTDU4/ZFXuXFhNxi7JP2RhuoGwBnM+S4A==} y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} @@ -2939,18 +2472,10 @@ packages: engines: {node: '>= 14.6'} hasBin: true - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - yargs-parser@22.0.0: resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yargs@17.7.3: - resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} - engines: {node: '>=12'} - yargs@18.0.0: resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} @@ -2959,10 +2484,6 @@ packages: resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} engines: {node: '>=12.20'} - yoctocolors-cjs@2.1.3: - resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} - engines: {node: '>=18'} - yoga-layout@3.2.1: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} @@ -2978,47 +2499,47 @@ snapshots: '@alcalzone/ansi-tokenize@0.2.5': dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.198': + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.198': + '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.198': + '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.198': + '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.198': + '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.198': + '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.198': + '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.198': + '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.201': optional: true - '@anthropic-ai/claude-agent-sdk@0.3.198(@anthropic-ai/sdk@0.106.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': + '@anthropic-ai/claude-agent-sdk@0.3.201(@anthropic-ai/sdk@0.106.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': dependencies: '@anthropic-ai/sdk': 0.106.0(zod@4.4.3) '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) zod: 4.4.3 optionalDependencies: - '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.198 - '@anthropic-ai/claude-agent-sdk-darwin-x64': 0.3.198 - '@anthropic-ai/claude-agent-sdk-linux-arm64': 0.3.198 - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl': 0.3.198 - '@anthropic-ai/claude-agent-sdk-linux-x64': 0.3.198 - '@anthropic-ai/claude-agent-sdk-linux-x64-musl': 0.3.198 - '@anthropic-ai/claude-agent-sdk-win32-arm64': 0.3.198 - '@anthropic-ai/claude-agent-sdk-win32-x64': 0.3.198 + '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.201 + '@anthropic-ai/claude-agent-sdk-darwin-x64': 0.3.201 + '@anthropic-ai/claude-agent-sdk-linux-arm64': 0.3.201 + '@anthropic-ai/claude-agent-sdk-linux-arm64-musl': 0.3.201 + '@anthropic-ai/claude-agent-sdk-linux-x64': 0.3.201 + '@anthropic-ai/claude-agent-sdk-linux-x64-musl': 0.3.201 + '@anthropic-ai/claude-agent-sdk-win32-arm64': 0.3.201 + '@anthropic-ai/claude-agent-sdk-win32-x64': 0.3.201 '@anthropic-ai/sdk@0.106.0(zod@4.4.3)': dependencies: @@ -3027,370 +2548,150 @@ snapshots: optionalDependencies: zod: 4.4.3 - '@aws-crypto/crc32@5.2.0': - dependencies: - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.8 - tslib: 2.8.1 - - '@aws-crypto/sha256-browser@5.2.0': - dependencies: - '@aws-crypto/sha256-js': 5.2.0 - '@aws-crypto/supports-web-crypto': 5.2.0 - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-locate-window': 3.965.5 - '@smithy/util-utf8': 2.3.0 - tslib: 2.8.1 - - '@aws-crypto/sha256-js@5.2.0': - dependencies: - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.8 - tslib: 2.8.1 - - '@aws-crypto/supports-web-crypto@5.2.0': - dependencies: - tslib: 2.8.1 - - '@aws-crypto/util@5.2.0': - dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/util-utf8': 2.3.0 - tslib: 2.8.1 - - '@aws-sdk/client-cognito-identity-provider@3.1045.0': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.8 - '@aws-sdk/credential-provider-node': 3.972.39 - '@aws-sdk/middleware-host-header': 3.972.10 - '@aws-sdk/middleware-logger': 3.972.10 - '@aws-sdk/middleware-recursion-detection': 3.972.11 - '@aws-sdk/middleware-user-agent': 3.972.38 - '@aws-sdk/region-config-resolver': 3.972.13 - '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-endpoints': 3.996.8 - '@aws-sdk/util-user-agent-browser': 3.972.10 - '@aws-sdk/util-user-agent-node': 3.973.24 - '@smithy/config-resolver': 4.5.1 - '@smithy/core': 3.24.1 - '@smithy/fetch-http-handler': 5.4.1 - '@smithy/hash-node': 4.3.1 - '@smithy/invalid-dependency': 4.3.1 - '@smithy/middleware-content-length': 4.3.1 - '@smithy/middleware-endpoint': 4.5.1 - '@smithy/middleware-retry': 4.6.1 - '@smithy/middleware-serde': 4.3.1 - '@smithy/middleware-stack': 4.3.1 - '@smithy/node-config-provider': 4.4.1 - '@smithy/node-http-handler': 4.7.1 - '@smithy/protocol-http': 5.4.1 - '@smithy/smithy-client': 4.13.1 - '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.3.1 - '@smithy/util-base64': 4.4.1 - '@smithy/util-body-length-browser': 4.3.1 - '@smithy/util-body-length-node': 4.3.1 - '@smithy/util-defaults-mode-browser': 4.4.1 - '@smithy/util-defaults-mode-node': 4.3.1 - '@smithy/util-endpoints': 3.5.1 - '@smithy/util-middleware': 4.3.1 - '@smithy/util-retry': 4.4.1 - '@smithy/util-utf8': 4.3.1 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/core@3.974.8': - dependencies: - '@aws-sdk/types': 3.973.8 - '@aws-sdk/xml-builder': 3.972.22 - '@smithy/core': 3.24.1 - '@smithy/node-config-provider': 4.4.1 - '@smithy/property-provider': 4.3.1 - '@smithy/protocol-http': 5.4.1 - '@smithy/signature-v4': 5.4.1 - '@smithy/smithy-client': 4.13.1 - '@smithy/types': 4.14.1 - '@smithy/util-base64': 4.4.1 - '@smithy/util-middleware': 4.3.1 - '@smithy/util-retry': 4.4.1 - '@smithy/util-utf8': 4.3.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-env@3.972.34': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.3.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-http@3.972.36': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/types': 3.973.8 - '@smithy/fetch-http-handler': 5.4.1 - '@smithy/node-http-handler': 4.7.1 - '@smithy/property-provider': 4.3.1 - '@smithy/protocol-http': 5.4.1 - '@smithy/smithy-client': 4.13.1 - '@smithy/types': 4.14.1 - '@smithy/util-stream': 4.6.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-ini@3.972.38': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/credential-provider-env': 3.972.34 - '@aws-sdk/credential-provider-http': 3.972.36 - '@aws-sdk/credential-provider-login': 3.972.38 - '@aws-sdk/credential-provider-process': 3.972.34 - '@aws-sdk/credential-provider-sso': 3.972.38 - '@aws-sdk/credential-provider-web-identity': 3.972.38 - '@aws-sdk/nested-clients': 3.997.6 - '@aws-sdk/types': 3.973.8 - '@smithy/credential-provider-imds': 4.3.1 - '@smithy/property-provider': 4.3.1 - '@smithy/shared-ini-file-loader': 4.5.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-login@3.972.38': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/nested-clients': 3.997.6 - '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.3.1 - '@smithy/protocol-http': 5.4.1 - '@smithy/shared-ini-file-loader': 4.5.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-node@3.972.39': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.34 - '@aws-sdk/credential-provider-http': 3.972.36 - '@aws-sdk/credential-provider-ini': 3.972.38 - '@aws-sdk/credential-provider-process': 3.972.34 - '@aws-sdk/credential-provider-sso': 3.972.38 - '@aws-sdk/credential-provider-web-identity': 3.972.38 - '@aws-sdk/types': 3.973.8 - '@smithy/credential-provider-imds': 4.3.1 - '@smithy/property-provider': 4.3.1 - '@smithy/shared-ini-file-loader': 4.5.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-process@3.972.34': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.3.1 - '@smithy/shared-ini-file-loader': 4.5.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-sso@3.972.38': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/nested-clients': 3.997.6 - '@aws-sdk/token-providers': 3.1041.0 - '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.3.1 - '@smithy/shared-ini-file-loader': 4.5.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-web-identity@3.972.38': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/nested-clients': 3.997.6 - '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.3.1 - '@smithy/shared-ini-file-loader': 4.5.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/middleware-host-header@3.972.10': + '@aws-sdk/client-cognito-identity-provider@3.1079.0': dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/protocol-http': 5.4.1 - '@smithy/types': 4.14.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/credential-provider-node': 3.972.62 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/fetch-http-handler': 5.6.3 + '@smithy/node-http-handler': 4.9.3 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.972.10': + '@aws-sdk/core@3.974.27': dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/types': 4.14.1 + '@aws-sdk/types': 3.973.15 + '@aws-sdk/xml-builder': 3.972.33 + '@aws/lambda-invoke-store': 0.3.0 + '@smithy/core': 3.29.1 + '@smithy/signature-v4': 5.6.2 + '@smithy/types': 4.15.1 + bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.972.11': + '@aws-sdk/credential-provider-env@3.972.53': dependencies: - '@aws-sdk/types': 3.973.8 - '@aws/lambda-invoke-store': 0.2.4 - '@smithy/protocol-http': 5.4.1 - '@smithy/types': 4.14.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.37': - dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-arn-parser': 3.972.3 - '@smithy/core': 3.24.1 - '@smithy/node-config-provider': 4.4.1 - '@smithy/protocol-http': 5.4.1 - '@smithy/signature-v4': 5.4.1 - '@smithy/smithy-client': 4.13.1 - '@smithy/types': 4.14.1 - '@smithy/util-config-provider': 4.3.1 - '@smithy/util-middleware': 4.3.1 - '@smithy/util-stream': 4.6.1 - '@smithy/util-utf8': 4.3.1 - tslib: 2.8.1 - - '@aws-sdk/middleware-user-agent@3.972.38': + '@aws-sdk/credential-provider-http@3.972.55': dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-endpoints': 3.996.8 - '@smithy/core': 3.24.1 - '@smithy/protocol-http': 5.4.1 - '@smithy/types': 4.14.1 - '@smithy/util-retry': 4.4.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/fetch-http-handler': 5.6.3 + '@smithy/node-http-handler': 4.9.3 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.6': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.8 - '@aws-sdk/middleware-host-header': 3.972.10 - '@aws-sdk/middleware-logger': 3.972.10 - '@aws-sdk/middleware-recursion-detection': 3.972.11 - '@aws-sdk/middleware-user-agent': 3.972.38 - '@aws-sdk/region-config-resolver': 3.972.13 - '@aws-sdk/signature-v4-multi-region': 3.996.25 - '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-endpoints': 3.996.8 - '@aws-sdk/util-user-agent-browser': 3.972.10 - '@aws-sdk/util-user-agent-node': 3.973.24 - '@smithy/config-resolver': 4.5.1 - '@smithy/core': 3.24.1 - '@smithy/fetch-http-handler': 5.4.1 - '@smithy/hash-node': 4.3.1 - '@smithy/invalid-dependency': 4.3.1 - '@smithy/middleware-content-length': 4.3.1 - '@smithy/middleware-endpoint': 4.5.1 - '@smithy/middleware-retry': 4.6.1 - '@smithy/middleware-serde': 4.3.1 - '@smithy/middleware-stack': 4.3.1 - '@smithy/node-config-provider': 4.4.1 - '@smithy/node-http-handler': 4.7.1 - '@smithy/protocol-http': 5.4.1 - '@smithy/smithy-client': 4.13.1 - '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.3.1 - '@smithy/util-base64': 4.4.1 - '@smithy/util-body-length-browser': 4.3.1 - '@smithy/util-body-length-node': 4.3.1 - '@smithy/util-defaults-mode-browser': 4.4.1 - '@smithy/util-defaults-mode-node': 4.3.1 - '@smithy/util-endpoints': 3.5.1 - '@smithy/util-middleware': 4.3.1 - '@smithy/util-retry': 4.4.1 - '@smithy/util-utf8': 4.3.1 + '@aws-sdk/credential-provider-ini@3.972.60': + dependencies: + '@aws-sdk/core': 3.974.27 + '@aws-sdk/credential-provider-env': 3.972.53 + '@aws-sdk/credential-provider-http': 3.972.55 + '@aws-sdk/credential-provider-login': 3.972.59 + '@aws-sdk/credential-provider-process': 3.972.53 + '@aws-sdk/credential-provider-sso': 3.972.59 + '@aws-sdk/credential-provider-web-identity': 3.972.59 + '@aws-sdk/nested-clients': 3.997.27 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/credential-provider-imds': 4.4.6 + '@smithy/types': 4.15.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - '@aws-sdk/region-config-resolver@3.972.13': + '@aws-sdk/credential-provider-login@3.972.59': dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/config-resolver': 4.5.1 - '@smithy/node-config-provider': 4.4.1 - '@smithy/types': 4.14.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/nested-clients': 3.997.27 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.25': - dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.37 - '@aws-sdk/types': 3.973.8 - '@smithy/protocol-http': 5.4.1 - '@smithy/signature-v4': 5.4.1 - '@smithy/types': 4.14.1 + '@aws-sdk/credential-provider-node@3.972.62': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.53 + '@aws-sdk/credential-provider-http': 3.972.55 + '@aws-sdk/credential-provider-ini': 3.972.60 + '@aws-sdk/credential-provider-process': 3.972.53 + '@aws-sdk/credential-provider-sso': 3.972.59 + '@aws-sdk/credential-provider-web-identity': 3.972.59 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/credential-provider-imds': 4.4.6 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1041.0': + '@aws-sdk/credential-provider-process@3.972.53': dependencies: - '@aws-sdk/core': 3.974.8 - '@aws-sdk/nested-clients': 3.997.6 - '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.3.1 - '@smithy/shared-ini-file-loader': 4.5.1 - '@smithy/types': 4.14.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - '@aws-sdk/types@3.973.8': + '@aws-sdk/credential-provider-sso@3.972.59': dependencies: - '@smithy/types': 4.14.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/nested-clients': 3.997.27 + '@aws-sdk/token-providers': 3.1079.0 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/util-arn-parser@3.972.3': + '@aws-sdk/credential-provider-web-identity@3.972.59': dependencies: + '@aws-sdk/core': 3.974.27 + '@aws-sdk/nested-clients': 3.997.27 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.996.8': + '@aws-sdk/nested-clients@3.997.27': dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.3.1 - '@smithy/util-endpoints': 3.5.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/signature-v4-multi-region': 3.996.38 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/fetch-http-handler': 5.6.3 + '@smithy/node-http-handler': 4.9.3 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/util-locate-window@3.965.5': + '@aws-sdk/signature-v4-multi-region@3.996.38': dependencies: + '@aws-sdk/types': 3.973.15 + '@smithy/signature-v4': 5.6.2 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.972.10': + '@aws-sdk/token-providers@3.1079.0': dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/types': 4.14.1 - bowser: 2.14.1 + '@aws-sdk/core': 3.974.27 + '@aws-sdk/nested-clients': 3.997.27 + '@aws-sdk/types': 3.973.15 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.973.24': + '@aws-sdk/types@3.973.15': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.38 - '@aws-sdk/types': 3.973.8 - '@smithy/node-config-provider': 4.4.1 - '@smithy/types': 4.14.1 - '@smithy/util-config-provider': 4.3.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.22': + '@aws-sdk/xml-builder@3.972.33': dependencies: - '@nodable/entities': 2.1.0 - '@smithy/types': 4.14.1 - fast-xml-parser: 5.7.2 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws/lambda-invoke-store@0.2.4': {} + '@aws/lambda-invoke-store@0.3.0': {} '@babel/helper-string-parser@7.29.7': {} @@ -3400,7 +2701,7 @@ snapshots: dependencies: '@babel/types': 7.29.7 - '@babel/runtime@7.28.6': {} + '@babel/runtime@7.29.7': {} '@babel/types@7.29.7': dependencies: @@ -3409,23 +2710,12 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@bundled-es-modules/cookie@2.0.1': - dependencies: - cookie: 0.7.2 - optional: true - - '@bundled-es-modules/statuses@1.0.1': - dependencies: - statuses: 2.0.2 - optional: true - - '@bundled-es-modules/tough-cookie@0.1.6': + '@clack/core@1.4.2': dependencies: - '@types/tough-cookie': 4.0.5 - tough-cookie: 4.1.4 - optional: true + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 - '@clack/core@1.4.2': + '@clack/core@1.4.3': dependencies: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 @@ -3437,202 +2727,103 @@ snapshots: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@esbuild/aix-ppc64@0.27.7': + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.28.1': + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/android-arm64@0.27.7': + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/android-arm64@0.28.1': + '@esbuild/aix-ppc64@0.28.1': optional: true - '@esbuild/android-arm@0.27.7': + '@esbuild/android-arm64@0.28.1': optional: true '@esbuild/android-arm@0.28.1': optional: true - '@esbuild/android-x64@0.27.7': - optional: true - '@esbuild/android-x64@0.28.1': optional: true - '@esbuild/darwin-arm64@0.27.7': - optional: true - '@esbuild/darwin-arm64@0.28.1': optional: true - '@esbuild/darwin-x64@0.27.7': - optional: true - '@esbuild/darwin-x64@0.28.1': optional: true - '@esbuild/freebsd-arm64@0.27.7': - optional: true - '@esbuild/freebsd-arm64@0.28.1': optional: true - '@esbuild/freebsd-x64@0.27.7': - optional: true - '@esbuild/freebsd-x64@0.28.1': optional: true - '@esbuild/linux-arm64@0.27.7': - optional: true - '@esbuild/linux-arm64@0.28.1': optional: true - '@esbuild/linux-arm@0.27.7': - optional: true - '@esbuild/linux-arm@0.28.1': optional: true - '@esbuild/linux-ia32@0.27.7': - optional: true - '@esbuild/linux-ia32@0.28.1': optional: true - '@esbuild/linux-loong64@0.27.7': - optional: true - '@esbuild/linux-loong64@0.28.1': optional: true - '@esbuild/linux-mips64el@0.27.7': - optional: true - '@esbuild/linux-mips64el@0.28.1': optional: true - '@esbuild/linux-ppc64@0.27.7': - optional: true - '@esbuild/linux-ppc64@0.28.1': optional: true - '@esbuild/linux-riscv64@0.27.7': - optional: true - '@esbuild/linux-riscv64@0.28.1': optional: true - '@esbuild/linux-s390x@0.27.7': - optional: true - '@esbuild/linux-s390x@0.28.1': optional: true - '@esbuild/linux-x64@0.27.7': - optional: true - '@esbuild/linux-x64@0.28.1': optional: true - '@esbuild/netbsd-arm64@0.27.7': - optional: true - '@esbuild/netbsd-arm64@0.28.1': optional: true - '@esbuild/netbsd-x64@0.27.7': - optional: true - '@esbuild/netbsd-x64@0.28.1': optional: true - '@esbuild/openbsd-arm64@0.27.7': - optional: true - '@esbuild/openbsd-arm64@0.28.1': optional: true - '@esbuild/openbsd-x64@0.27.7': - optional: true - '@esbuild/openbsd-x64@0.28.1': optional: true - '@esbuild/openharmony-arm64@0.27.7': - optional: true - '@esbuild/openharmony-arm64@0.28.1': optional: true - '@esbuild/sunos-x64@0.27.7': - optional: true - '@esbuild/sunos-x64@0.28.1': optional: true - '@esbuild/win32-arm64@0.27.7': - optional: true - '@esbuild/win32-arm64@0.28.1': optional: true - '@esbuild/win32-ia32@0.27.7': - optional: true - '@esbuild/win32-ia32@0.28.1': optional: true - '@esbuild/win32-x64@0.27.7': - optional: true - '@esbuild/win32-x64@0.28.1': optional: true - '@hono/node-server@1.19.14(hono@4.11.4)': - dependencies: - hono: 4.11.4 - - '@hono/node-server@1.19.14(hono@4.12.27)': - dependencies: - hono: 4.12.27 - - '@inquirer/ansi@1.0.2': - optional: true - - '@inquirer/confirm@5.1.21(@types/node@22.20.0)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@22.20.0) - '@inquirer/type': 3.0.10(@types/node@22.20.0) - optionalDependencies: - '@types/node': 22.20.0 - optional: true - - '@inquirer/core@10.3.2(@types/node@22.20.0)': + '@hono/node-server@1.19.14(hono@4.12.28)': dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.20.0) - cli-width: 4.1.0 - mute-stream: 2.0.0 - signal-exit: 4.1.0 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 22.20.0 - optional: true - - '@inquirer/figures@1.0.15': - optional: true - - '@inquirer/type@3.0.10(@types/node@22.20.0)': - optionalDependencies: - '@types/node': 22.20.0 - optional: true + hono: 4.12.28 '@jridgewell/resolve-uri@3.1.2': {} @@ -3645,7 +2836,7 @@ snapshots: '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': dependencies: - '@hono/node-server': 1.19.14(hono@4.12.27) + '@hono/node-server': 1.19.14(hono@4.12.28) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 @@ -3655,7 +2846,7 @@ snapshots: eventsource-parser: 3.1.0 express: 5.2.1 express-rate-limit: 8.5.2(express@5.2.1) - hono: 4.12.27 + hono: 4.12.28 jose: 6.2.3 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -3665,16 +2856,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@mswjs/interceptors@0.39.8': - dependencies: - '@open-draft/deferred-promise': 2.2.0 - '@open-draft/logger': 0.3.0 - '@open-draft/until': 2.1.0 - is-node-process: 1.2.0 - outvariant: 1.4.3 - strict-event-emitter: 0.5.1 - optional: true - '@napi-rs/keyring-darwin-arm64@1.3.0': optional: true @@ -3726,34 +2907,28 @@ snapshots: '@napi-rs/keyring-win32-ia32-msvc': 1.3.0 '@napi-rs/keyring-win32-x64-msvc': 1.3.0 - '@nodable/entities@2.1.0': {} + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@nodable/entities@2.2.0': {} '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.0 - - '@open-draft/deferred-promise@2.2.0': - optional: true + '@nodelib/fs.stat@2.0.5': {} - '@open-draft/logger@0.3.0': + '@nodelib/fs.walk@1.2.8': dependencies: - is-node-process: 1.2.0 - outvariant: 1.4.3 - optional: true - - '@open-draft/until@2.1.0': - optional: true + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 - '@opentelemetry/api@1.9.0': - optional: true + '@oxc-project/types@0.138.0': {} '@oxfmt/binding-android-arm-eabi@0.56.0': optional: true @@ -3812,61 +2987,61 @@ snapshots: '@oxfmt/binding-win32-x64-msvc@0.56.0': optional: true - '@oxlint/binding-android-arm-eabi@1.71.0': + '@oxlint/binding-android-arm-eabi@1.72.0': optional: true - '@oxlint/binding-android-arm64@1.71.0': + '@oxlint/binding-android-arm64@1.72.0': optional: true - '@oxlint/binding-darwin-arm64@1.71.0': + '@oxlint/binding-darwin-arm64@1.72.0': optional: true - '@oxlint/binding-darwin-x64@1.71.0': + '@oxlint/binding-darwin-x64@1.72.0': optional: true - '@oxlint/binding-freebsd-x64@1.71.0': + '@oxlint/binding-freebsd-x64@1.72.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.71.0': + '@oxlint/binding-linux-arm-gnueabihf@1.72.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.71.0': + '@oxlint/binding-linux-arm-musleabihf@1.72.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.71.0': + '@oxlint/binding-linux-arm64-gnu@1.72.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.71.0': + '@oxlint/binding-linux-arm64-musl@1.72.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.71.0': + '@oxlint/binding-linux-ppc64-gnu@1.72.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.71.0': + '@oxlint/binding-linux-riscv64-gnu@1.72.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.71.0': + '@oxlint/binding-linux-riscv64-musl@1.72.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.71.0': + '@oxlint/binding-linux-s390x-gnu@1.72.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.71.0': + '@oxlint/binding-linux-x64-gnu@1.72.0': optional: true - '@oxlint/binding-linux-x64-musl@1.71.0': + '@oxlint/binding-linux-x64-musl@1.72.0': optional: true - '@oxlint/binding-openharmony-arm64@1.71.0': + '@oxlint/binding-openharmony-arm64@1.72.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.71.0': + '@oxlint/binding-win32-arm64-msvc@1.72.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.71.0': + '@oxlint/binding-win32-ia32-msvc@1.72.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.71.0': + '@oxlint/binding-win32-x64-msvc@1.72.0': optional: true '@polka/url@1.0.0-next.29': {} @@ -3885,277 +3060,113 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - '@redocly/config@0.49.1': + '@redocly/config@0.50.1': dependencies: json-schema-to-ts: 2.7.2 - '@redocly/openapi-core@2.36.0': + '@redocly/openapi-core@2.37.0': dependencies: '@redocly/ajv': 8.18.3 - '@redocly/config': 0.49.1 + '@redocly/config': 0.50.1 ajv: '@redocly/ajv@8.18.1' ajv-formats: 3.0.1(@redocly/ajv@8.18.1) colorette: 1.4.0 + graphql: 16.14.2 js-levenshtein: 1.1.6 js-yaml: 4.3.0 - picomatch: 4.0.4 + picomatch: 4.0.5 pluralize: 8.0.0 yaml-ast-parser: 0.0.43 - '@rollup/rollup-android-arm-eabi@4.62.2': - optional: true - - '@rollup/rollup-android-arm64@4.62.2': - optional: true - - '@rollup/rollup-darwin-arm64@4.62.2': - optional: true - - '@rollup/rollup-darwin-x64@4.62.2': - optional: true - - '@rollup/rollup-freebsd-arm64@4.62.2': + '@rolldown/binding-android-arm64@1.1.4': optional: true - '@rollup/rollup-freebsd-x64@4.62.2': + '@rolldown/binding-darwin-arm64@1.1.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + '@rolldown/binding-darwin-x64@1.1.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.62.2': + '@rolldown/binding-freebsd-x64@1.1.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.62.2': + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.62.2': + '@rolldown/binding-linux-arm64-gnu@1.1.4': optional: true - '@rollup/rollup-linux-loong64-gnu@4.62.2': + '@rolldown/binding-linux-arm64-musl@1.1.4': optional: true - '@rollup/rollup-linux-loong64-musl@4.62.2': + '@rolldown/binding-linux-ppc64-gnu@1.1.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.62.2': + '@rolldown/binding-linux-s390x-gnu@1.1.4': optional: true - '@rollup/rollup-linux-ppc64-musl@4.62.2': + '@rolldown/binding-linux-x64-gnu@1.1.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.62.2': + '@rolldown/binding-linux-x64-musl@1.1.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.62.2': + '@rolldown/binding-openharmony-arm64@1.1.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.62.2': - optional: true - - '@rollup/rollup-linux-x64-musl@4.62.2': - optional: true - - '@rollup/rollup-openbsd-x64@4.62.2': - optional: true - - '@rollup/rollup-openharmony-arm64@4.62.2': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.62.2': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.62.2': + '@rolldown/binding-wasm32-wasi@1.1.4': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true - '@rollup/rollup-win32-x64-gnu@4.62.2': + '@rolldown/binding-win32-arm64-msvc@1.1.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.62.2': + '@rolldown/binding-win32-x64-msvc@1.1.4': optional: true - '@smithy/config-resolver@4.5.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/core@3.24.1': - dependencies: - '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/credential-provider-imds@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/fetch-http-handler@5.4.1': - dependencies: - '@smithy/core': 3.24.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/hash-node@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/invalid-dependency@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/is-array-buffer@2.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/middleware-content-length@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/middleware-endpoint@4.5.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/middleware-retry@4.6.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/middleware-serde@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/middleware-stack@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/node-config-provider@4.4.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/node-http-handler@4.7.1': - dependencies: - '@smithy/core': 3.24.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/property-provider@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/protocol-http@5.4.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/shared-ini-file-loader@4.5.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/signature-v4@5.4.1': - dependencies: - '@smithy/core': 3.24.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/smithy-client@4.13.1': - dependencies: - '@smithy/core': 3.24.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/types@4.14.1': - dependencies: - tslib: 2.8.1 - - '@smithy/url-parser@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/util-base64@4.4.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/util-body-length-browser@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/util-body-length-node@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/util-buffer-from@2.2.0': - dependencies: - '@smithy/is-array-buffer': 2.2.0 - tslib: 2.8.1 - - '@smithy/util-config-provider@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/util-defaults-mode-browser@4.4.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 - - '@smithy/util-defaults-mode-node@4.3.1': - dependencies: - '@smithy/core': 3.24.1 - tslib: 2.8.1 + '@rolldown/pluginutils@1.0.1': {} - '@smithy/util-endpoints@3.5.1': + '@smithy/core@3.29.1': dependencies: - '@smithy/core': 3.24.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@smithy/util-middleware@4.3.1': + '@smithy/credential-provider-imds@4.4.6': dependencies: - '@smithy/core': 3.24.1 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@smithy/util-retry@4.4.1': + '@smithy/fetch-http-handler@5.6.3': dependencies: - '@smithy/core': 3.24.1 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@smithy/util-stream@4.6.1': + '@smithy/node-http-handler@4.9.3': dependencies: - '@smithy/core': 3.24.1 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@smithy/util-utf8@2.3.0': + '@smithy/signature-v4@5.6.2': dependencies: - '@smithy/util-buffer-from': 2.2.0 + '@smithy/core': 3.29.1 + '@smithy/types': 4.15.1 tslib: 2.8.1 - '@smithy/util-utf8@4.3.1': + '@smithy/types@4.15.1': dependencies: - '@smithy/core': 3.24.1 tslib: 2.8.1 '@stablelib/base64@1.0.1': {} '@standard-schema/spec@1.1.0': {} - '@statelyai/inspect@0.7.2(xstate@5.32.2)': + '@statelyai/inspect@0.7.2(xstate@5.32.4)': dependencies: fast-safe-stringify: 2.1.1 isomorphic-ws: 5.0.0(ws@8.21.0) @@ -4163,19 +3174,21 @@ snapshots: safe-stable-stringify: 2.5.0 superjson: 1.13.3 ws: 8.21.0 - xstate: 5.32.2 + xstate: 5.32.4 transitivePeerDependencies: - bufferutil - utf-8-validate + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 - '@types/cookie@0.6.0': - optional: true - '@types/deep-eql@4.0.2': {} '@types/estree@1.0.9': {} @@ -4196,22 +3209,16 @@ snapshots: '@types/semver@7.7.1': {} - '@types/statuses@2.0.6': - optional: true - - '@types/tough-cookie@4.0.5': - optional: true - '@types/yargs-parser@21.0.3': {} '@types/yargs@17.0.35': dependencies: '@types/yargs-parser': 21.0.3 - '@vitest/coverage-v8@4.1.9(vitest@4.1.9)': + '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.9 + '@vitest/utils': 4.1.10 ast-v8-to-istanbul: 1.0.4 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -4220,58 +3227,57 @@ snapshots: obug: 2.1.3 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.9(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.9)(@vitest/ui@4.1.9)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0)) + vitest: 4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) - '@vitest/expect@4.1.9': + '@vitest/expect@4.1.10': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.9(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.9 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - msw: 2.10.4(@types/node@22.20.0)(typescript@5.9.3) - vite: 7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0) - '@vitest/pretty-format@4.1.9': + '@vitest/pretty-format@4.1.10': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.9': + '@vitest/runner@4.1.10': dependencies: - '@vitest/utils': 4.1.9 + '@vitest/utils': 4.1.10 pathe: 2.0.3 - '@vitest/snapshot@4.1.9': + '@vitest/snapshot@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.9 - '@vitest/utils': 4.1.9 + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.9': {} + '@vitest/spy@4.1.10': {} - '@vitest/ui@4.1.9(vitest@4.1.9)': + '@vitest/ui@4.1.10(vitest@4.1.10)': dependencies: - '@vitest/utils': 4.1.9 + '@vitest/utils': 4.1.10 fflate: 0.8.3 flatted: 3.4.2 pathe: 2.0.3 sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vitest: 4.1.9(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.9)(@vitest/ui@4.1.9)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0)) + vitest: 4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) - '@vitest/utils@4.1.9': + '@vitest/utils@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.9 + '@vitest/pretty-format': 4.1.10 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -4281,26 +3287,25 @@ snapshots: dependencies: eventemitter3: 5.0.4 - '@workos/migrations@2.4.0': + '@workos/migrations@2.5.0': dependencies: - '@aws-sdk/client-cognito-identity-provider': 3.1045.0 + '@aws-sdk/client-cognito-identity-provider': 3.1079.0 '@workos-inc/node': 10.7.0 chalk: 5.6.2 cli-progress: 3.12.0 commander: 15.0.0 csv-parse: 6.2.1 - csv-stringify: 6.7.0 + csv-stringify: 6.8.1 dotenv: 17.4.2 - fast-xml-parser: 5.8.0 + fast-xml-parser: 5.9.3 google-auth-library: 10.9.0 prompts: 2.4.2 transitivePeerDependencies: - - aws-crt - supports-color '@workos/oagen@0.23.0': dependencies: - '@redocly/openapi-core': 2.36.0 + '@redocly/openapi-core': 2.37.0 commander: 13.1.0 dotenv: 17.4.2 tree-sitter: 0.21.1 @@ -4313,7 +3318,7 @@ snapshots: tree-sitter-ruby: 0.21.0(tree-sitter@0.21.1) tree-sitter-rust: 0.21.0(tree-sitter@0.21.1) tree-sitter-typescript: 0.23.2(tree-sitter@0.21.1) - tsx: 4.22.4 + tsx: 4.23.0 typescript: 6.0.3 transitivePeerDependencies: - tree_sitter @@ -4356,19 +3361,12 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} - ansi-regex@6.2.2: {} - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - optional: true - - ansi-styles@6.2.1: {} - ansi-styles@6.2.3: {} + anynum@1.0.1: {} + argparse@2.0.1: {} assertion-error@2.0.1: {} @@ -4391,7 +3389,7 @@ snapshots: content-type: 2.0.0 debug: 4.4.3 http-errors: 2.0.1 - iconv-lite: 0.7.2 + iconv-lite: 0.7.3 on-finished: 2.4.1 qs: 6.15.3 raw-body: 3.0.2 @@ -4437,39 +3435,21 @@ snapshots: dependencies: string-width: 4.2.3 - cli-truncate@5.1.1: + cli-truncate@5.2.0: dependencies: - slice-ansi: 7.1.2 - string-width: 8.2.0 - - cli-width@4.1.0: - optional: true - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - optional: true + slice-ansi: 8.0.0 + string-width: 8.2.1 cliui@9.0.1: dependencies: string-width: 7.2.0 - strip-ansi: 7.1.0 - wrap-ansi: 9.0.0 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 code-excerpt@4.0.0: dependencies: convert-to-spaces: 2.0.1 - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - optional: true - - color-name@1.1.4: - optional: true - colorette@1.4.0: {} commander@13.1.0: {} @@ -4509,7 +3489,7 @@ snapshots: csv-parse@6.2.1: {} - csv-stringify@6.7.0: {} + csv-stringify@6.8.1: {} data-uri-to-buffer@4.0.1: {} @@ -4528,6 +3508,8 @@ snapshots: depd@2.0.0: {} + detect-libc@2.1.2: {} + diff@8.0.4: {} dotenv@17.4.2: {} @@ -4544,7 +3526,7 @@ snapshots: ee-first@1.1.1: {} - emoji-regex@10.4.0: {} + emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} @@ -4556,42 +3538,13 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.2.0: {} + es-module-lexer@2.3.0: {} es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 - es-toolkit@1.44.0: {} - - esbuild@0.27.7: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.7 - '@esbuild/android-arm': 0.27.7 - '@esbuild/android-arm64': 0.27.7 - '@esbuild/android-x64': 0.27.7 - '@esbuild/darwin-arm64': 0.27.7 - '@esbuild/darwin-x64': 0.27.7 - '@esbuild/freebsd-arm64': 0.27.7 - '@esbuild/freebsd-x64': 0.27.7 - '@esbuild/linux-arm': 0.27.7 - '@esbuild/linux-arm64': 0.27.7 - '@esbuild/linux-ia32': 0.27.7 - '@esbuild/linux-loong64': 0.27.7 - '@esbuild/linux-mips64el': 0.27.7 - '@esbuild/linux-ppc64': 0.27.7 - '@esbuild/linux-riscv64': 0.27.7 - '@esbuild/linux-s390x': 0.27.7 - '@esbuild/linux-x64': 0.27.7 - '@esbuild/netbsd-arm64': 0.27.7 - '@esbuild/netbsd-x64': 0.27.7 - '@esbuild/openbsd-arm64': 0.27.7 - '@esbuild/openbsd-x64': 0.27.7 - '@esbuild/openharmony-arm64': 0.27.7 - '@esbuild/sunos-x64': 0.27.7 - '@esbuild/win32-arm64': 0.27.7 - '@esbuild/win32-ia32': 0.27.7 - '@esbuild/win32-x64': 0.27.7 + es-toolkit@1.49.0: {} esbuild@0.28.1: optionalDependencies: @@ -4712,33 +3665,27 @@ snapshots: dependencies: fast-string-width: 3.0.2 - fast-xml-builder@1.2.0: + fast-xml-builder@1.2.1: dependencies: - path-expression-matcher: 1.5.0 + path-expression-matcher: 1.6.1 xml-naming: 0.1.0 - fast-xml-parser@5.7.2: - dependencies: - '@nodable/entities': 2.1.0 - fast-xml-builder: 1.2.0 - path-expression-matcher: 1.5.0 - strnum: 2.3.0 - - fast-xml-parser@5.8.0: + fast-xml-parser@5.9.3: dependencies: - '@nodable/entities': 2.1.0 - fast-xml-builder: 1.2.0 - path-expression-matcher: 1.5.0 - strnum: 2.3.0 + '@nodable/entities': 2.2.0 + fast-xml-builder: 1.2.1 + is-unsafe: 1.0.1 + path-expression-matcher: 1.6.1 + strnum: 2.4.1 xml-naming: 0.1.0 - fastq@1.19.0: + fastq@1.20.1: dependencies: - reusify: 1.0.4 + reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.4): + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: - picomatch: 4.0.4 + picomatch: 4.0.5 fetch-blob@3.2.0: dependencies: @@ -4777,7 +3724,7 @@ snapshots: function-bind@1.1.2: {} - gaxios@7.1.5: + gaxios@7.1.6: dependencies: extend: 3.0.2 https-proxy-agent: 7.0.6 @@ -4787,7 +3734,7 @@ snapshots: gcp-metadata@8.1.2: dependencies: - gaxios: 7.1.5 + gaxios: 7.1.6 google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -4795,9 +3742,7 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.3.0: {} - - get-east-asian-width@1.5.0: {} + get-east-asian-width@1.6.0: {} get-intrinsic@1.3.0: dependencies: @@ -4825,7 +3770,7 @@ snapshots: dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.5 + gaxios: 7.1.6 gcp-metadata: 8.1.2 google-logging-utils: 1.1.3 jws: 4.0.1 @@ -4836,8 +3781,7 @@ snapshots: gopd@1.2.0: {} - graphql@16.14.2: - optional: true + graphql@16.14.2: {} has-flag@4.0.0: {} @@ -4847,12 +3791,7 @@ snapshots: dependencies: function-bind: 1.1.2 - headers-polyfill@4.0.3: - optional: true - - hono@4.11.4: {} - - hono@4.12.27: {} + hono@4.12.28: {} html-escaper@2.0.2: {} @@ -4871,7 +3810,7 @@ snapshots: transitivePeerDependencies: - supports-color - iconv-lite@0.7.2: + iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 @@ -4883,14 +3822,14 @@ snapshots: dependencies: '@alcalzone/ansi-tokenize': 0.2.5 ansi-escapes: 7.3.0 - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 auto-bind: 5.0.1 chalk: 5.6.2 cli-boxes: 3.0.0 cli-cursor: 4.0.0 - cli-truncate: 5.1.1 + cli-truncate: 5.2.0 code-excerpt: 4.0.0 - es-toolkit: 1.44.0 + es-toolkit: 1.49.0 indent-string: 5.0.0 is-in-ci: 2.0.0 patch-console: 2.0.0 @@ -4900,12 +3839,12 @@ snapshots: signal-exit: 3.0.7 slice-ansi: 8.0.0 stack-utils: 2.0.6 - string-width: 8.2.0 + string-width: 8.2.1 terminal-size: 4.0.1 - type-fest: 5.4.4 + type-fest: 5.8.0 widest-line: 6.0.0 - wrap-ansi: 9.0.0 - ws: 8.19.0 + wrap-ansi: 9.0.2 + ws: 8.21.0 yoga-layout: 3.2.1 optionalDependencies: '@types/react': 19.2.17 @@ -4923,13 +3862,9 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@5.0.0: - dependencies: - get-east-asian-width: 1.3.0 - is-fullwidth-code-point@5.1.0: dependencies: - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 is-glob@4.0.3: dependencies: @@ -4943,13 +3878,12 @@ snapshots: dependencies: is-docker: 3.0.0 - is-node-process@1.2.0: - optional: true - is-number@7.0.0: {} is-promise@4.0.0: {} + is-unsafe@1.0.1: {} + is-what@4.1.16: {} is-wsl@1.1.0: {} @@ -4993,19 +3927,21 @@ snapshots: json-schema-to-ts@2.7.2: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.7 '@types/json-schema': 7.0.15 ts-algebra: 1.2.2 json-schema-to-ts@3.1.1: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.7 ts-algebra: 2.0.0 json-schema-traverse@1.0.0: {} json-schema-typed@8.0.2: {} + jsonc-parser@3.3.1: {} + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 @@ -5019,6 +3955,55 @@ snapshots: kleur@3.0.3: {} + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -5058,35 +4043,6 @@ snapshots: ms@2.1.3: {} - msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3): - dependencies: - '@bundled-es-modules/cookie': 2.0.1 - '@bundled-es-modules/statuses': 1.0.1 - '@bundled-es-modules/tough-cookie': 0.1.6 - '@inquirer/confirm': 5.1.21(@types/node@22.20.0) - '@mswjs/interceptors': 0.39.8 - '@open-draft/deferred-promise': 2.2.0 - '@open-draft/until': 2.1.0 - '@types/cookie': 0.6.0 - '@types/statuses': 2.0.6 - graphql: 16.14.2 - headers-polyfill: 4.0.3 - is-node-process: 1.2.0 - outvariant: 1.4.3 - path-to-regexp: 6.3.0 - picocolors: 1.1.1 - strict-event-emitter: 0.5.1 - type-fest: 4.41.0 - yargs: 17.7.3 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - '@types/node' - optional: true - - mute-stream@2.0.0: - optional: true - nanoid@3.3.15: {} negotiator@1.0.0: {} @@ -5136,9 +4092,6 @@ snapshots: dependencies: is-wsl: 1.1.0 - outvariant@1.4.3: - optional: true - oxfmt@0.56.0: dependencies: tinypool: 2.1.0 @@ -5163,27 +4116,27 @@ snapshots: '@oxfmt/binding-win32-ia32-msvc': 0.56.0 '@oxfmt/binding-win32-x64-msvc': 0.56.0 - oxlint@1.71.0: + oxlint@1.72.0: optionalDependencies: - '@oxlint/binding-android-arm-eabi': 1.71.0 - '@oxlint/binding-android-arm64': 1.71.0 - '@oxlint/binding-darwin-arm64': 1.71.0 - '@oxlint/binding-darwin-x64': 1.71.0 - '@oxlint/binding-freebsd-x64': 1.71.0 - '@oxlint/binding-linux-arm-gnueabihf': 1.71.0 - '@oxlint/binding-linux-arm-musleabihf': 1.71.0 - '@oxlint/binding-linux-arm64-gnu': 1.71.0 - '@oxlint/binding-linux-arm64-musl': 1.71.0 - '@oxlint/binding-linux-ppc64-gnu': 1.71.0 - '@oxlint/binding-linux-riscv64-gnu': 1.71.0 - '@oxlint/binding-linux-riscv64-musl': 1.71.0 - '@oxlint/binding-linux-s390x-gnu': 1.71.0 - '@oxlint/binding-linux-x64-gnu': 1.71.0 - '@oxlint/binding-linux-x64-musl': 1.71.0 - '@oxlint/binding-openharmony-arm64': 1.71.0 - '@oxlint/binding-win32-arm64-msvc': 1.71.0 - '@oxlint/binding-win32-ia32-msvc': 1.71.0 - '@oxlint/binding-win32-x64-msvc': 1.71.0 + '@oxlint/binding-android-arm-eabi': 1.72.0 + '@oxlint/binding-android-arm64': 1.72.0 + '@oxlint/binding-darwin-arm64': 1.72.0 + '@oxlint/binding-darwin-x64': 1.72.0 + '@oxlint/binding-freebsd-x64': 1.72.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.72.0 + '@oxlint/binding-linux-arm-musleabihf': 1.72.0 + '@oxlint/binding-linux-arm64-gnu': 1.72.0 + '@oxlint/binding-linux-arm64-musl': 1.72.0 + '@oxlint/binding-linux-ppc64-gnu': 1.72.0 + '@oxlint/binding-linux-riscv64-gnu': 1.72.0 + '@oxlint/binding-linux-riscv64-musl': 1.72.0 + '@oxlint/binding-linux-s390x-gnu': 1.72.0 + '@oxlint/binding-linux-x64-gnu': 1.72.0 + '@oxlint/binding-linux-x64-musl': 1.72.0 + '@oxlint/binding-openharmony-arm64': 1.72.0 + '@oxlint/binding-win32-arm64-msvc': 1.72.0 + '@oxlint/binding-win32-ia32-msvc': 1.72.0 + '@oxlint/binding-win32-x64-msvc': 1.72.0 p-limit@7.3.0: dependencies: @@ -5197,13 +4150,10 @@ snapshots: patch-console@2.0.0: {} - path-expression-matcher@1.5.0: {} + path-expression-matcher@1.6.1: {} path-key@3.1.1: {} - path-to-regexp@6.3.0: - optional: true - path-to-regexp@8.4.2: {} pathe@2.0.3: {} @@ -5212,7 +4162,7 @@ snapshots: picomatch@2.3.2: {} - picomatch@4.0.4: {} + picomatch@4.0.5: {} pkce-challenge@5.0.1: {} @@ -5236,22 +4186,11 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - psl@1.15.0: - dependencies: - punycode: 2.3.1 - optional: true - - punycode@2.3.1: - optional: true - qs@6.15.3: dependencies: es-define-property: 1.0.1 side-channel: 1.1.1 - querystringify@2.2.0: - optional: true - queue-microtask@1.2.3: {} range-parser@1.3.0: {} @@ -5260,7 +4199,7 @@ snapshots: dependencies: bytes: 3.1.2 http-errors: 2.0.1 - iconv-lite: 0.7.2 + iconv-lite: 0.7.3 unpipe: 1.0.0 react-reconciler@0.33.0(react@19.2.7): @@ -5270,51 +4209,35 @@ snapshots: react@19.2.7: {} - require-directory@2.1.1: - optional: true - require-from-string@2.0.2: {} - requires-port@1.0.0: - optional: true - restore-cursor@4.0.0: dependencies: onetime: 5.1.2 signal-exit: 3.0.7 - reusify@1.0.4: {} + reusify@1.1.0: {} - rollup@4.62.2: + rolldown@1.1.4: dependencies: - '@types/estree': 1.0.9 + '@oxc-project/types': 0.138.0 + '@rolldown/pluginutils': 1.0.1 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.3 + '@rolldown/binding-android-arm64': 1.1.4 + '@rolldown/binding-darwin-arm64': 1.1.4 + '@rolldown/binding-darwin-x64': 1.1.4 + '@rolldown/binding-freebsd-x64': 1.1.4 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.4 + '@rolldown/binding-linux-arm64-gnu': 1.1.4 + '@rolldown/binding-linux-arm64-musl': 1.1.4 + '@rolldown/binding-linux-ppc64-gnu': 1.1.4 + '@rolldown/binding-linux-s390x-gnu': 1.1.4 + '@rolldown/binding-linux-x64-gnu': 1.1.4 + '@rolldown/binding-linux-x64-musl': 1.1.4 + '@rolldown/binding-openharmony-arm64': 1.1.4 + '@rolldown/binding-wasm32-wasi': 1.1.4 + '@rolldown/binding-win32-arm64-msvc': 1.1.4 + '@rolldown/binding-win32-x64-msvc': 1.1.4 router@2.2.0: dependencies: @@ -5407,9 +4330,6 @@ snapshots: signal-exit@3.0.7: {} - signal-exit@4.1.0: - optional: true - sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -5418,11 +4338,6 @@ snapshots: sisteransi@1.0.5: {} - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 5.0.0 - slice-ansi@8.0.0: dependencies: ansi-styles: 6.2.3 @@ -5445,9 +4360,6 @@ snapshots: std-env@4.1.0: {} - strict-event-emitter@0.5.1: - optional: true - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -5456,28 +4368,26 @@ snapshots: string-width@7.2.0: dependencies: - emoji-regex: 10.4.0 - get-east-asian-width: 1.3.0 - strip-ansi: 7.1.0 + emoji-regex: 10.6.0 + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 - string-width@8.2.0: + string-width@8.2.1: dependencies: - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - strip-ansi@7.2.0: dependencies: ansi-regex: 6.2.2 - strnum@2.3.0: {} + strnum@2.4.1: + dependencies: + anynum: 1.0.1 superjson@1.13.3: dependencies: @@ -5497,8 +4407,8 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 tinypool@2.1.0: {} @@ -5512,14 +4422,6 @@ snapshots: totalist@3.0.1: {} - tough-cookie@4.1.4: - dependencies: - psl: 1.15.0 - punycode: 2.3.1 - universalify: 0.2.0 - url-parse: 1.5.10 - optional: true - tree-sitter-c-sharp@0.23.1(tree-sitter@0.21.1): dependencies: node-addon-api: 8.9.0 @@ -5597,16 +4499,13 @@ snapshots: tslib@2.8.1: {} - tsx@4.22.4: + tsx@4.23.0: dependencies: esbuild: 0.28.1 optionalDependencies: fsevents: 2.3.3 - type-fest@4.41.0: - optional: true - - type-fest@5.4.4: + type-fest@5.8.0: dependencies: tagged-tag: 1.0.0 @@ -5622,62 +4521,52 @@ snapshots: undici-types@6.21.0: {} - universalify@0.2.0: - optional: true - unpipe@1.0.0: {} - url-parse@1.5.10: - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - optional: true - uuid@13.0.2: {} vary@1.1.2: {} - vite@7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0): + vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0): dependencies: - esbuild: 0.27.7 - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + lightningcss: 1.32.0 + picomatch: 4.0.5 postcss: 8.5.16 - rollup: 4.62.2 + rolldown: 1.1.4 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 22.20.0 + esbuild: 0.28.1 fsevents: 2.3.3 - tsx: 4.22.4 + tsx: 4.23.0 yaml: 2.9.0 - vitest@4.1.9(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.9)(@vitest/ui@4.1.9)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0)): + vitest@4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.9 - '@vitest/mocker': 4.1.9(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.9 - '@vitest/runner': 4.1.9 - '@vitest/snapshot': 4.1.9 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 - es-module-lexer: 2.2.0 + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.0 expect-type: 1.4.0 magic-string: 0.30.21 obug: 2.1.3 pathe: 2.0.3 - picomatch: 4.0.4 + picomatch: 4.0.5 std-env: 4.1.0 tinybench: 2.9.0 tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 7.3.1(@types/node@22.20.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@opentelemetry/api': 1.9.0 '@types/node': 22.20.0 - '@vitest/coverage-v8': 4.1.9(vitest@4.1.9) - '@vitest/ui': 4.1.9(vitest@4.1.9) + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) + '@vitest/ui': 4.1.10(vitest@4.1.10) transitivePeerDependencies: - msw @@ -5694,32 +4583,16 @@ snapshots: widest-line@6.0.0: dependencies: - string-width: 8.2.0 - - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - optional: true - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - optional: true + string-width: 8.2.1 - wrap-ansi@9.0.0: + wrap-ansi@9.0.2: dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 string-width: 7.2.0 - strip-ansi: 7.1.0 + strip-ansi: 7.2.0 wrappy@1.0.2: {} - ws@8.19.0: {} - ws@8.21.0: {} wsl-utils@0.3.1: @@ -5729,7 +4602,7 @@ snapshots: xml-naming@0.1.0: {} - xstate@5.32.2: {} + xstate@5.32.4: {} y18n@5.0.8: {} @@ -5737,22 +4610,8 @@ snapshots: yaml@2.9.0: {} - yargs-parser@21.1.1: - optional: true - yargs-parser@22.0.0: {} - yargs@17.7.3: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - optional: true - yargs@18.0.0: dependencies: cliui: 9.0.1 @@ -5764,9 +4623,6 @@ snapshots: yocto-queue@1.2.2: {} - yoctocolors-cjs@2.1.3: - optional: true - yoga-layout@3.2.1: {} zod-to-json-schema@3.25.2(zod@4.4.3): diff --git a/src/bin.ts b/src/bin.ts index 6eb01b67..7b7ee6a8 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -466,6 +466,51 @@ async function runCli(): Promise { ); return yargs.demandCommand(1, 'Please specify a skills subcommand').strict(); }) + .command('mcp', 'Manage the WorkOS MCP server in coding agents (Claude Code, Codex, Cursor)', (yargs) => { + registerSubcommand( + yargs, + 'install', + 'Add the WorkOS MCP server to detected coding agents', + (y) => + y.option('agent', { + alias: 'a', + type: 'array', + string: true, + description: 'Target specific agent(s): claude-code, codex, cursor', + }), + async (argv) => { + const { runMcpInstall } = await import('./commands/mcp.js'); + await runMcpInstall({ agent: argv.agent as string[] | undefined }); + }, + ); + registerSubcommand( + yargs, + 'remove', + 'Remove the WorkOS MCP server from coding agents', + (y) => + y.option('agent', { + alias: 'a', + type: 'array', + string: true, + description: 'Target specific agent(s): claude-code, codex, cursor', + }), + async (argv) => { + const { runMcpRemove } = await import('./commands/mcp.js'); + await runMcpRemove({ agent: argv.agent as string[] | undefined }); + }, + ); + registerSubcommand( + yargs, + 'status', + 'Show which coding agents have the WorkOS MCP server configured', + (y) => y, + async () => { + const { runMcpStatus } = await import('./commands/mcp.js'); + await runMcpStatus(); + }, + ); + return yargs.demandCommand(1, 'Please specify an mcp subcommand').strict(); + }) .command( 'doctor', 'Diagnose WorkOS AuthKit integration issues in the current project', diff --git a/src/commands/mcp.spec.ts b/src/commands/mcp.spec.ts new file mode 100644 index 00000000..cd7d2332 --- /dev/null +++ b/src/commands/mcp.spec.ts @@ -0,0 +1,431 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, rmSync } from 'fs'; +import { join } from 'path'; +import { homedir, tmpdir } from 'os'; + +// Mock the shell-out layer so Claude Code / Codex outcomes are scripted. +vi.mock('../utils/exec-file.js', () => ({ + execFileNoThrow: vi.fn(), +})); + +// clack.log writes to the raw stdout/stderr streams (not console.*), so capture +// its human-mode output through a module mock instead of a console spy. +const { clackLogs } = vi.hoisted(() => ({ clackLogs: [] as string[] })); +vi.mock('../utils/clack.js', () => { + const record = (msg: unknown) => { + clackLogs.push(String(msg)); + }; + return { + default: { + log: { info: record, success: record, error: record, warn: record, step: record, message: record }, + }, + }; +}); + +// Point homedir at a real temp dir so Cursor's fs read-modify-write and the +// config-dir detection checks operate on disk without touching the real $HOME. +vi.mock('os', async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, homedir: vi.fn(actual.homedir) }; +}); + +const { execFileNoThrow } = await import('../utils/exec-file.js'); +const { setOutputMode } = await import('../utils/output.js'); +const { CliExit } = await import('../utils/cli-exit.js'); +const { createMcpClients, detectMcpClients, MCP_AGENT_KEYS } = await import('../lib/mcp-clients.js'); +const { runMcpInstall, runMcpRemove, runMcpStatus } = await import('./mcp.js'); + +type ExecShape = { status: number; stdout?: string; stderr?: string }; + +/** Route exec calls; anything the impl doesn't override defaults to success. */ +function mockExec(impl: (command: string, args: string[]) => ExecShape): void { + vi.mocked(execFileNoThrow).mockImplementation((command: string, args: string[]) => + Promise.resolve({ status: 0, stdout: '', stderr: '', ...impl(command, args) }), + ); +} + +function clientByKey(key: string) { + const target = createMcpClients().find((c) => c.key === key); + if (!target) throw new Error(`no client ${key}`); + return target; +} + +/** Grab a thrown CliExit (handlers exit by throwing, not returning). */ +async function captureExit(fn: () => Promise): Promise | undefined> { + try { + await fn(); + return undefined; + } catch (e) { + if (e instanceof CliExit) return e; + throw e; + } +} + +let testHome: string; +let consoleOutput: string[]; + +beforeEach(() => { + vi.clearAllMocks(); + clackLogs.length = 0; + testHome = mkdtempSync(join(tmpdir(), 'mcp-test-')); + vi.mocked(homedir).mockReturnValue(testHome); + // Default: every shell-out succeeds (overridden per test). + mockExec(() => ({ status: 0 })); + consoleOutput = []; + vi.spyOn(console, 'log').mockImplementation((...args: unknown[]) => { + consoleOutput.push(args.map(String).join(' ')); + }); + vi.spyOn(console, 'error').mockImplementation((...args: unknown[]) => { + consoleOutput.push(args.map(String).join(' ')); + }); +}); + +afterEach(() => { + rmSync(testHome, { recursive: true, force: true }); + setOutputMode('human'); + vi.restoreAllMocks(); +}); + +function makeDir(name: string): void { + mkdirSync(join(testHome, name), { recursive: true }); +} + +function cursorConfigPath(): string { + return join(testHome, '.cursor', 'mcp.json'); +} + +function writeCursorConfig(content: string): void { + makeDir('.cursor'); + writeFileSync(cursorConfigPath(), content, 'utf8'); +} + +describe('createMcpClients', () => { + it('returns the three client targets in a stable order', () => { + const clients = createMcpClients(); + expect(clients.map((c) => c.key)).toEqual(['claude-code', 'codex', 'cursor']); + }); + + it('exposes the known agent keys for validation', () => { + expect(MCP_AGENT_KEYS).toEqual(['claude-code', 'codex', 'cursor']); + }); +}); + +describe('detectMcpClients', () => { + it('reports a CLI client available only when dir AND binary are present', async () => { + makeDir('.claude'); + mockExec((_c, args) => (args[0] === '--version' ? { status: 0 } : { status: 0 })); + expect((await detectMcpClients(['claude-code'])).map((c) => c.key)).toEqual(['claude-code']); + }); + + it('reports a CLI client unavailable when the binary is missing', async () => { + makeDir('.claude'); + mockExec((_c, args) => (args[0] === '--version' ? { status: 1, stderr: 'command not found' } : { status: 0 })); + expect(await detectMcpClients(['claude-code'])).toEqual([]); + }); + + it('reports a CLI client unavailable when the config dir is missing', async () => { + // No ~/.claude dir; binary would run, but the dir gate fails first. + mockExec(() => ({ status: 0 })); + expect(await detectMcpClients(['claude-code'])).toEqual([]); + }); + + it('detects Cursor from its config dir alone (no binary)', async () => { + makeDir('.cursor'); + expect((await detectMcpClients(['cursor'])).map((c) => c.key)).toEqual(['cursor']); + }); + + it('narrows to the requested agent filter', async () => { + makeDir('.claude'); + makeDir('.codex'); + makeDir('.cursor'); + const detected = await detectMcpClients(['cursor']); + expect(detected.map((c) => c.key)).toEqual(['cursor']); + }); + + it('returns nothing for an unknown filter key', async () => { + makeDir('.claude'); + expect(await detectMcpClients(['bogus'])).toEqual([]); + }); +}); + +describe('Claude Code client', () => { + const claude = () => clientByKey('claude-code'); + + it('add maps a clean exit to installed', async () => { + mockExec(() => ({ status: 0 })); + expect((await claude().add()).outcome).toBe('installed'); + }); + + it('add maps an "already exists" collision to already-installed', async () => { + mockExec(() => ({ status: 1, stderr: 'MCP server workos already exists in user scope' })); + expect((await claude().add()).outcome).toBe('already-installed'); + }); + + it('add maps a version gap (unknown --transport) to failed with an excerpt', async () => { + mockExec(() => ({ status: 1, stderr: "error: unknown option '--transport'" })); + const res = await claude().add(); + expect(res.outcome).toBe('failed'); + expect(res.error).toContain('--transport'); + }); + + it('isInstalled matches the workos: list line', async () => { + mockExec(() => ({ status: 0, stdout: 'raindrop: https://x (HTTP)\nworkos: https://mcp.workos.com/mcp (HTTP) - Connected' })); + expect(await claude().isInstalled()).toBe(true); + }); + + it('isInstalled does NOT match a workos-docs substring collision', async () => { + mockExec(() => ({ status: 0, stdout: 'workos-docs: https://docs (HTTP) - Connected' })); + expect(await claude().isInstalled()).toBe(false); + }); + + it('isInstalled is false when list itself fails', async () => { + mockExec(() => ({ status: 1, stderr: 'boom' })); + expect(await claude().isInstalled()).toBe(false); + }); + + it('remove maps a clean exit to removed', async () => { + mockExec(() => ({ status: 0 })); + expect((await claude().remove()).outcome).toBe('removed'); + }); + + it('remove maps "No MCP server named" (exit 1) to not-installed', async () => { + mockExec(() => ({ status: 1, stderr: 'No MCP server named "workos" in user scope' })); + expect((await claude().remove()).outcome).toBe('not-installed'); + }); +}); + +describe('Codex client', () => { + const codex = () => clientByKey('codex'); + + it('add maps a clean exit to installed', async () => { + mockExec(() => ({ status: 0 })); + expect((await codex().add()).outcome).toBe('installed'); + }); + + it('add maps a version gap (unknown --url) to failed', async () => { + mockExec(() => ({ status: 1, stderr: "error: unexpected argument '--url'" })); + const res = await codex().add(); + expect(res.outcome).toBe('failed'); + expect(res.error).toContain('--url'); + }); + + it('add reports installed when a non-zero exit still persisted the server (OAuth-flow timeout)', async () => { + // Codex writes the config, then its post-add OAuth flow blocks and times + // out with a non-zero status — but `mcp list` proves the server landed. + mockExec((_c, args) => { + if (args.includes('add')) return { status: 1, stdout: "Added global MCP server 'workos'." }; + if (args.includes('list')) return { status: 0, stdout: 'workos https://mcp.workos.com/mcp enabled' }; + return { status: 0 }; + }); + expect((await codex().add()).outcome).toBe('installed'); + }); + + it('add stays failed on a non-zero exit when the server did NOT land', async () => { + mockExec((_c, args) => { + if (args.includes('add')) return { status: 1, stderr: 'boom' }; + if (args.includes('list')) return { status: 0, stdout: 'Name Url\ngithub https://x' }; + return { status: 0 }; + }); + expect((await codex().add()).outcome).toBe('failed'); + }); + + it('isInstalled matches the codex table row (name in first column, no colon)', async () => { + mockExec(() => ({ + status: 0, + stdout: 'Name Url\ngithub https://api.github\nworkos https://mcp.workos.com/mcp enabled', + })); + expect(await codex().isInstalled()).toBe(true); + }); + + it('remove maps "No MCP server named" (exit 0) to not-installed', async () => { + mockExec(() => ({ status: 0, stdout: "No MCP server named 'workos' found." })); + expect((await codex().remove()).outcome).toBe('not-installed'); + }); +}); + +describe('Cursor client', () => { + const cursor = () => clientByKey('cursor'); + const val = `{ "url": "https://mcp.workos.com/mcp" }`; + + it('add creates the file when none exists', async () => { + const res = await cursor().add(); + expect(res.outcome).toBe('installed'); + const written = JSON.parse(readFileSync(cursorConfigPath(), 'utf8')); + expect(written.mcpServers.workos.url).toBe('https://mcp.workos.com/mcp'); + }); + + it('add handles an empty file', async () => { + writeCursorConfig(''); + expect((await cursor().add()).outcome).toBe('installed'); + const written = JSON.parse(readFileSync(cursorConfigPath(), 'utf8')); + expect(written.mcpServers.workos.url).toBe('https://mcp.workos.com/mcp'); + }); + + it('add preserves unrelated servers and comments', async () => { + writeCursorConfig('{\n // keep me\n "mcpServers": {\n "other": { "url": "https://other" }\n }\n}'); + expect((await cursor().add()).outcome).toBe('installed'); + const raw = readFileSync(cursorConfigPath(), 'utf8'); + expect(raw).toContain('// keep me'); + expect(raw).toContain('"other"'); + expect(raw).toContain('https://mcp.workos.com/mcp'); + }); + + it('add tolerates a trailing comma (valid JSONC, not malformed)', async () => { + writeCursorConfig('{ "mcpServers": { "other": { "url": "https://other" } }, }'); + expect((await cursor().add()).outcome).toBe('installed'); + }); + + it('add on a malformed file fails WITHOUT overwriting it', async () => { + const malformed = '{ "mcpServers": '; + writeCursorConfig(malformed); + const res = await cursor().add(); + expect(res.outcome).toBe('failed'); + expect(res.error).toContain('fix it manually'); + expect(readFileSync(cursorConfigPath(), 'utf8')).toBe(malformed); + }); + + it('add overwrites an existing workos key with a different URL (idempotent converge)', async () => { + writeCursorConfig('{ "mcpServers": { "workos": { "url": "https://old" } } }'); + expect((await cursor().add()).outcome).toBe('installed'); + const written = JSON.parse(readFileSync(cursorConfigPath(), 'utf8')); + expect(written.mcpServers.workos.url).toBe('https://mcp.workos.com/mcp'); + }); + + it('isInstalled reflects presence of the workos key', async () => { + writeCursorConfig(`{ "mcpServers": { "workos": ${val} } }`); + expect(await cursor().isInstalled()).toBe(true); + writeCursorConfig('{ "mcpServers": { "other": { "url": "x" } } }'); + expect(await cursor().isInstalled()).toBe(false); + }); + + it('remove drops only the workos key, preserving others', async () => { + writeCursorConfig('{ "mcpServers": { "workos": { "url": "https://w" }, "other": { "url": "https://o" } } }'); + expect((await cursor().remove()).outcome).toBe('removed'); + const written = JSON.parse(readFileSync(cursorConfigPath(), 'utf8')); + expect(written.mcpServers.workos).toBeUndefined(); + expect(written.mcpServers.other.url).toBe('https://o'); + }); + + it('remove is a no-op (not-installed) when the file is absent', async () => { + expect((await cursor().remove()).outcome).toBe('not-installed'); + }); + + it('remove is a no-op (not-installed) when the key is absent', async () => { + writeCursorConfig('{ "mcpServers": { "other": { "url": "x" } } }'); + expect((await cursor().remove()).outcome).toBe('not-installed'); + }); +}); + +describe('runMcpInstall / runMcpRemove (human mode)', () => { + it('acts on all detected agents and prints the matrix', async () => { + makeDir('.claude'); + makeDir('.codex'); + makeDir('.cursor'); + mockExec(() => ({ status: 0 })); + await runMcpInstall(); + const joined = clackLogs.join('\n'); + expect(joined).toContain('Claude Code'); + expect(joined).toContain('Codex'); + expect(joined).toContain('Cursor'); + }); + + it('prints the no-agents message and exits 0 when none are detected', async () => { + mockExec((_c, args) => (args[0] === '--version' ? { status: 1 } : { status: 0 })); + const exit = await captureExit(() => runMcpInstall()); + expect(exit).toBeUndefined(); + expect(clackLogs.join('\n')).toContain('No supported coding agents detected'); + }); + + it('exits 1 when any agent fails, after emitting the full matrix', async () => { + makeDir('.claude'); + makeDir('.cursor'); + // Claude add fails hard; Cursor add succeeds. Matrix must include both. + mockExec((_c, args) => { + if (args.includes('add')) return { status: 1, stderr: 'kaboom' }; + return { status: 0 }; + }); + const exit = await captureExit(() => runMcpInstall()); + expect(exit?.exitCode).toBe(1); + const joined = clackLogs.join('\n'); + expect(joined).toContain('Claude Code'); + expect(joined).toContain('Cursor'); + }); + + it('narrows to --agent claude-code', async () => { + makeDir('.claude'); + makeDir('.codex'); + makeDir('.cursor'); + setOutputMode('json'); + await runMcpInstall({ agent: ['claude-code'] }); + const output = JSON.parse(consoleOutput[0]); + expect(output.data.agents).toHaveLength(1); + expect(output.data.agents[0].agent).toBe('claude-code'); + }); + + it('rejects an unknown --agent with a structured error and exit 1', async () => { + const exit = await captureExit(() => runMcpInstall({ agent: ['bogus'] })); + expect(exit?.exitCode).toBe(1); + expect(consoleOutput.join('\n')).toContain('Unknown agent'); + }); +}); + +describe('JSON output mode', () => { + beforeEach(() => { + setOutputMode('json'); + }); + + it('runMcpInstall emits status ok with a per-agent matrix', async () => { + makeDir('.claude'); + makeDir('.cursor'); + mockExec(() => ({ status: 0 })); + await runMcpInstall(); + const output = JSON.parse(consoleOutput[0]); + expect(output.status).toBe('ok'); + expect(output.data.agents.map((a: { agent: string }) => a.agent).sort()).toEqual(['claude-code', 'cursor']); + expect(output.data.agents.every((a: { outcome: string }) => a.outcome === 'installed')).toBe(true); + }); + + it('runMcpInstall with zero agents emits an empty matrix and exits 0', async () => { + mockExec((_c, args) => (args[0] === '--version' ? { status: 1 } : { status: 0 })); + const exit = await captureExit(() => runMcpInstall()); + expect(exit).toBeUndefined(); + const output = JSON.parse(consoleOutput[0]); + expect(output.status).toBe('ok'); + expect(output.data.agents).toEqual([]); + }); + + it('runMcpInstall still emits the full matrix before exiting 1 on failure', async () => { + makeDir('.claude'); + makeDir('.cursor'); + mockExec((_c, args) => (args.includes('add') && args.includes('--transport') ? { status: 1, stderr: 'bad' } : { status: 0 })); + const exit = await captureExit(() => runMcpInstall()); + expect(exit?.exitCode).toBe(1); + const output = JSON.parse(consoleOutput[0]); + const claude = output.data.agents.find((a: { agent: string }) => a.agent === 'claude-code'); + const cursor = output.data.agents.find((a: { agent: string }) => a.agent === 'cursor'); + expect(claude.outcome).toBe('failed'); + expect(cursor.outcome).toBe('installed'); + }); + + it('runMcpRemove emits status ok with outcomes', async () => { + makeDir('.cursor'); + writeCursorConfig('{ "mcpServers": { "workos": { "url": "https://w" } } }'); + await runMcpRemove({ agent: ['cursor'] }); + const output = JSON.parse(consoleOutput[0]); + expect(output.status).toBe('ok'); + expect(output.data.agents[0].outcome).toBe('removed'); + }); + + it('runMcpStatus emits { data: { agents: [...] } } with availability + install flags', async () => { + makeDir('.cursor'); + writeCursorConfig('{ "mcpServers": { "workos": { "url": "https://w" } } }'); + mockExec((_c, args) => (args[0] === '--version' ? { status: 1 } : { status: 0 })); + await runMcpStatus(); + const output = JSON.parse(consoleOutput[0]); + expect(output.data.agents).toHaveLength(3); + const cursor = output.data.agents.find((a: { agent: string }) => a.agent === 'cursor'); + expect(cursor).toMatchObject({ agent: 'cursor', displayName: 'Cursor', available: true, installed: true }); + const claude = output.data.agents.find((a: { agent: string }) => a.agent === 'claude-code'); + expect(claude).toMatchObject({ available: false, installed: false }); + }); +}); diff --git a/src/commands/mcp.ts b/src/commands/mcp.ts new file mode 100644 index 00000000..10ce1170 --- /dev/null +++ b/src/commands/mcp.ts @@ -0,0 +1,136 @@ +import clack from '../utils/clack.js'; +import { outputSuccess, outputJson, outputTable, exitWithError, isJsonMode } from '../utils/output.js'; +import { ExitCode, exitWithCode } from '../utils/exit-codes.js'; +import { + createMcpClients, + detectMcpClients, + MCP_AGENT_KEYS, + type McpAgentKey, + type McpClientResult, +} from '../lib/mcp-clients.js'; + +/** + * `workos mcp install | remove | status` handlers. + * + * Thin callers over `lib/mcp-clients.ts`: detect the clients, run the + * operation, and format the per-agent matrix in both output modes. No prompts + * (non-TTY-safe by construction) and no auth guard — the WorkOS MCP server is + * secret-free, so configuring it never needs an API key. + */ + +export interface McpCommandOptions { + agent?: string[]; +} + +/** Human phrasing for each outcome (JSON mode emits the raw `outcome` value). */ +const OUTCOME_LABEL: Record = { + installed: 'installed', + 'already-installed': 'already installed', + removed: 'removed', + 'not-installed': 'not installed', + skipped: 'skipped', + failed: 'failed', +}; + +/** + * Validate `--agent` values against known keys. Unknown values exit with a + * structured `unknown_agent` error. Returns undefined (no filter) when none + * were passed, so callers act on all detected agents. + */ +function resolveAgentFilter(agent?: string[]): McpAgentKey[] | undefined { + if (!agent || agent.length === 0) return undefined; + const unknown = agent.filter((a) => !MCP_AGENT_KEYS.includes(a as McpAgentKey)); + if (unknown.length > 0) { + exitWithError({ + code: 'unknown_agent', + message: `Unknown agent(s): ${unknown.join(', ')}. Supported: ${MCP_AGENT_KEYS.join(', ')}.`, + }); + } + return agent as McpAgentKey[]; +} + +/** Zero detected agents: same message + exit 0 for both install and remove. */ +function reportNoAgents(): void { + if (isJsonMode()) { + outputSuccess('No supported coding agents detected', { agents: [] }); + } else { + clack.log.info('No supported coding agents detected (looked for Claude Code, Codex, Cursor).'); + } +} + +/** + * Emit the per-agent matrix, then exit non-zero if any agent failed. The full + * matrix is always emitted first so partial success is still fully reported. + */ +function reportResults(message: string, results: McpClientResult[]): void { + if (isJsonMode()) { + outputSuccess(message, { agents: results }); + } else { + for (const r of results) { + const line = `${r.displayName}: ${OUTCOME_LABEL[r.outcome]}`; + if (r.outcome === 'failed') { + clack.log.error(r.error ? `${line} — ${r.error}` : line); + } else if (r.outcome === 'installed' || r.outcome === 'removed' || r.outcome === 'already-installed') { + clack.log.success(line); + } else { + clack.log.info(line); + } + } + } + + if (results.some((r) => r.outcome === 'failed')) { + exitWithCode(ExitCode.GENERAL_ERROR); + } +} + +export async function runMcpInstall(options: McpCommandOptions = {}): Promise { + const filter = resolveAgentFilter(options.agent); + const clients = await detectMcpClients(filter); + if (clients.length === 0) { + reportNoAgents(); + return; + } + const results: McpClientResult[] = []; + for (const client of clients) { + results.push(await client.add()); + } + reportResults('Configured WorkOS MCP server', results); +} + +export async function runMcpRemove(options: McpCommandOptions = {}): Promise { + const filter = resolveAgentFilter(options.agent); + const clients = await detectMcpClients(filter); + if (clients.length === 0) { + reportNoAgents(); + return; + } + const results: McpClientResult[] = []; + for (const client of clients) { + results.push(await client.remove()); + } + reportResults('Removed WorkOS MCP server', results); +} + +export async function runMcpStatus(): Promise { + // Status lists every known agent (not just available ones) with its + // availability + install flags, so `createMcpClients()` — not + // `detectMcpClients()` — is the right source here. + const clients = createMcpClients(); + const agents = await Promise.all( + clients.map(async (client) => { + const available = await client.isAvailable(); + const installed = available ? await client.isInstalled() : false; + return { agent: client.key, displayName: client.displayName, available, installed }; + }), + ); + + if (isJsonMode()) { + outputJson({ data: { agents } }); + return; + } + + outputTable( + [{ header: 'Agent' }, { header: 'Available' }, { header: 'Installed' }], + agents.map((a) => [a.displayName, a.available ? 'yes' : 'no', a.installed ? 'yes' : 'no']), + ); +} diff --git a/src/lib/constants.ts b/src/lib/constants.ts index f16189f8..0163dee4 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -36,6 +36,16 @@ export const ANALYTICS_ENABLED = settings.telemetry.enabled; export const INSTALLER_INTERACTION_EVENT_NAME = settings.telemetry.eventName; export const OAUTH_PORT = settings.legacy.oauthPort; +/** + * WorkOS MCP server identity, shared by the `mcp` command group and the + * per-client writers in `lib/mcp-clients.ts`. + * + * The server is secret-free: HTTP transport with OAuth handled by each client + * on first connect, so configuring it never requires CLI auth. + */ +export const MCP_SERVER_NAME = 'workos'; +export const MCP_SERVER_URL = 'https://mcp.workos.com/mcp'; + /** * Common glob patterns to ignore when searching for files. * Used by multiple integrations. diff --git a/src/lib/mcp-clients.ts b/src/lib/mcp-clients.ts new file mode 100644 index 00000000..7dd091e6 --- /dev/null +++ b/src/lib/mcp-clients.ts @@ -0,0 +1,310 @@ +import { homedir } from 'os'; +import { join } from 'path'; +import { access, mkdir, readFile, writeFile } from 'fs/promises'; +import * as jsonc from 'jsonc-parser'; +import { execFileNoThrow } from '../utils/exec-file.js'; +import { MCP_SERVER_NAME, MCP_SERVER_URL } from './constants.js'; + +/** + * Client-writer library for the WorkOS MCP server. + * + * One `McpClientTarget` interface, three implementations. Claude Code and Codex + * are configured by shelling out to their own CLIs (robust to their config + * format changes); Cursor has no CLI, so we merge `~/.cursor/mcp.json` directly + * with `jsonc-parser` (hand-edited files may contain comments / trailing + * commas). Every operation degrades to a reported outcome — a missing binary, + * an old client without HTTP-transport support, or an unparseable config is a + * `failed`/`skipped`/`not-installed` result, never a thrown error. + * + * The library owns detection and per-client config writing; callers (the `mcp` + * command today; install-flow / doctor in Phase 2) stay thin. Nothing here may + * assume it runs inside the `mcp` command. + */ + +/** 10s ceiling on every CLI shell-out so a hung client can't wedge the caller. */ +const EXEC_TIMEOUT_MS = 10_000; + +/** jsonc parse options: tolerate the comments / trailing commas real users + * hand-edit into `~/.cursor/mcp.json`, and an empty file, so only genuinely + * malformed JSON is flagged. */ +const JSONC_PARSE_OPTIONS: jsonc.ParseOptions = { + allowTrailingComma: true, + allowEmptyContent: true, +}; + +const JSONC_MODIFY_OPTIONS: jsonc.ModificationOptions = { + formattingOptions: { tabSize: 2, insertSpaces: true }, +}; + +export type McpAgentKey = 'claude-code' | 'codex' | 'cursor'; + +export type McpOutcome = + | 'installed' + | 'already-installed' + | 'removed' + | 'not-installed' + | 'skipped' + | 'failed'; + +export interface McpClientResult { + agent: McpAgentKey; + displayName: string; + outcome: McpOutcome; + /** stderr/message excerpt when `outcome === 'failed'`. */ + error?: string; +} + +export interface McpClientTarget { + key: McpAgentKey; + displayName: string; + /** Agent is usable on this machine (config dir present AND, for CLI clients, binary runnable). */ + isAvailable(): Promise; + /** The WorkOS server is present in this client's config. */ + isInstalled(): Promise; + add(): Promise; + remove(): Promise; +} + +/** Stable list of known agent keys, for `--agent` validation by callers. */ +export const MCP_AGENT_KEYS: McpAgentKey[] = ['claude-code', 'codex', 'cursor']; + +/** Async existence check — `access` rejects with ENOENT when the path is missing. */ +async function pathExists(p: string): Promise { + try { + await access(p); + return true; + } catch { + return false; + } +} + +/** Trim a shell-out message to a single-line excerpt for the `error` field. */ +function excerpt(raw: string): string { + const text = raw.trim(); + if (!text) return 'Unknown error'; + const firstLine = text.split('\n').find((l) => l.trim().length > 0) ?? text; + return firstLine.trim().slice(0, 300); +} + +/** + * Does a CLI `mcp list` output contain our server? + * + * Matches the first whitespace-delimited token of any line (with an optional + * trailing colon stripped), which covers both list shapes we support: + * - Claude Code: `workos: https://mcp.workos.com/mcp (HTTP) - ✔ Connected` + * - Codex table: `workos https://mcp.workos.com/mcp ...` + * + * First-token matching avoids the substring collision a naive + * `output.includes('workos')` would hit on an unrelated `workos-docs` entry. + */ +function listHasServer(stdout: string, name: string): boolean { + return stdout.split('\n').some((line) => { + const firstToken = line.trim().split(/\s+/)[0] ?? ''; + return firstToken.replace(/:$/, '') === name; + }); +} + +/** + * Shared shell-out client for Claude Code and Codex. The two differ only in + * binary name, config dir, and the `add` arg shape; every outcome-mapping rule + * is identical, so they share one implementation. + */ +function createCliClient(config: { + key: McpAgentKey; + displayName: string; + binary: string; + configDir: string; + addArgs: string[]; + removeArgs: string[]; +}): McpClientTarget { + const { key, displayName, binary, configDir, addArgs, removeArgs } = config; + const result = (outcome: McpOutcome, error?: string): McpClientResult => ({ + agent: key, + displayName, + outcome, + ...(error ? { error } : {}), + }); + + async function checkInstalled(): Promise { + const res = await execFileNoThrow(binary, ['mcp', 'list'], { timeout: EXEC_TIMEOUT_MS }); + if (res.status !== 0) return false; + return listHasServer(res.stdout, MCP_SERVER_NAME); + } + + return { + key, + displayName, + async isAvailable() { + // Two layers: the config dir can exist while the binary isn't on PATH, + // and vice versa — require both before we try to shell out. + if (!(await pathExists(join(homedir(), configDir)))) return false; + const res = await execFileNoThrow(binary, ['--version'], { timeout: EXEC_TIMEOUT_MS }); + return res.status === 0; + }, + isInstalled: checkInstalled, + async add() { + const res = await execFileNoThrow(binary, addArgs, { timeout: EXEC_TIMEOUT_MS }); + if (res.status === 0) return result('installed'); + // Idempotent: an "already exists" collision is a success, not a failure. + const combined = `${res.stdout}\n${res.stderr}`.toLowerCase(); + if (combined.includes('already exists') || combined.includes('already configured')) { + return result('already-installed'); + } + // A non-zero exit doesn't always mean the write failed: Codex persists the + // server config and THEN starts an OAuth flow that blocks (no browser / + // callback available here) until our timeout kills it with a non-zero + // status. Confirm against the actual config before declaring failure — + // more robust than matching each client's success wording. + if (await checkInstalled()) return result('installed'); + // Otherwise a real failure — an old client lacking `--transport http` / + // `--url`, a bad invocation, etc. Reported, never thrown. + return result('failed', excerpt(res.stderr || res.stdout)); + }, + async remove() { + const res = await execFileNoThrow(binary, removeArgs, { timeout: EXEC_TIMEOUT_MS }); + const combined = `${res.stdout}\n${res.stderr}`.toLowerCase(); + // Claude exits 1 and Codex exits 0 when the server is absent; both print + // "No MCP server named ...". Treat either as an idempotent no-op. + if (combined.includes('no mcp server')) return result('not-installed'); + if (res.status === 0) return result('removed'); + return result('failed', excerpt(res.stderr || res.stdout)); + }, + }; +} + +function createClaudeCodeClient(): McpClientTarget { + return createCliClient({ + key: 'claude-code', + displayName: 'Claude Code', + binary: 'claude', + configDir: '.claude', + // User scope: the management MCP is account-level, not per-repo — project + // scope would nag teammates via checked-in config. + addArgs: ['mcp', 'add', '--transport', 'http', '--scope', 'user', MCP_SERVER_NAME, MCP_SERVER_URL], + removeArgs: ['mcp', 'remove', '--scope', 'user', MCP_SERVER_NAME], + }); +} + +function createCodexClient(): McpClientTarget { + return createCliClient({ + key: 'codex', + displayName: 'Codex', + binary: 'codex', + configDir: '.codex', + addArgs: ['mcp', 'add', MCP_SERVER_NAME, '--url', MCP_SERVER_URL], + removeArgs: ['mcp', 'remove', MCP_SERVER_NAME], + }); +} + +/** + * Cursor has no CLI, so we read-modify-write `~/.cursor/mcp.json` directly with + * `jsonc-parser`, preserving existing servers, comments, and formatting. + */ +function createCursorClient(): McpClientTarget { + const key: McpAgentKey = 'cursor'; + const displayName = 'Cursor'; + const cursorDir = () => join(homedir(), '.cursor'); + const configPath = () => join(cursorDir(), 'mcp.json'); + const result = (outcome: McpOutcome, error?: string): McpClientResult => ({ + agent: key, + displayName, + outcome, + ...(error ? { error } : {}), + }); + + /** Read + parse the config. `parseError` is true only for genuinely malformed + * JSON (not comments / trailing commas / empty). */ + async function readConfig(): Promise<{ + content: string; + parsed: Record | undefined; + parseError: boolean; + exists: boolean; + }> { + const path = configPath(); + if (!(await pathExists(path))) { + return { content: '', parsed: undefined, parseError: false, exists: false }; + } + const content = await readFile(path, 'utf8'); + const errors: jsonc.ParseError[] = []; + const parsed = jsonc.parse(content, errors, JSONC_PARSE_OPTIONS) as Record | undefined; + return { content, parsed, parseError: errors.length > 0, exists: true }; + } + + function hasWorkosServer(parsed: Record | undefined): boolean { + const servers = parsed?.mcpServers; + return Boolean(servers && typeof servers === 'object' && MCP_SERVER_NAME in (servers as object)); + } + + return { + key, + displayName, + async isAvailable() { + return pathExists(cursorDir()); + }, + async isInstalled() { + try { + const { parsed, parseError } = await readConfig(); + if (parseError) return false; + return hasWorkosServer(parsed); + } catch { + return false; + } + }, + async add() { + const path = configPath(); + try { + const { content, parseError, exists } = await readConfig(); + // Never overwrite a file we couldn't parse — the user must fix it first. + if (exists && parseError) { + return result('failed', `Could not parse ${path}; fix it manually and retry.`); + } + await mkdir(cursorDir(), { recursive: true }); + // Converge to our URL — an existing `workos` key with a different URL is + // overwritten (reported as `installed`). + const edits = jsonc.modify( + content, + ['mcpServers', MCP_SERVER_NAME], + { url: MCP_SERVER_URL }, + JSONC_MODIFY_OPTIONS, + ); + await writeFile(path, jsonc.applyEdits(content, edits), 'utf8'); + return result('installed'); + } catch (error) { + return result('failed', error instanceof Error ? error.message : 'Unknown error'); + } + }, + async remove() { + const path = configPath(); + try { + const { content, parsed, parseError, exists } = await readConfig(); + if (!exists) return result('not-installed'); + if (parseError) { + return result('failed', `Could not parse ${path}; fix it manually and retry.`); + } + if (!hasWorkosServer(parsed)) return result('not-installed'); + const edits = jsonc.modify(content, ['mcpServers', MCP_SERVER_NAME], undefined, JSONC_MODIFY_OPTIONS); + await writeFile(path, jsonc.applyEdits(content, edits), 'utf8'); + return result('removed'); + } catch (error) { + return result('failed', error instanceof Error ? error.message : 'Unknown error'); + } + }, + }; +} + +/** The three client targets, in a stable order. */ +export function createMcpClients(): McpClientTarget[] { + return [createClaudeCodeClient(), createCodexClient(), createCursorClient()]; +} + +/** + * Return only the clients available on this machine, optionally narrowed to + * `agentFilter` keys. Availability is probed in parallel. An unknown filter key + * simply matches nothing here — callers validate keys and surface the error. + */ +export async function detectMcpClients(agentFilter?: string[]): Promise { + const clients = createMcpClients(); + const filtered = agentFilter ? clients.filter((c) => agentFilter.includes(c.key)) : clients; + const availability = await Promise.all(filtered.map((c) => c.isAvailable())); + return filtered.filter((_, i) => availability[i]); +} diff --git a/src/utils/help-json.ts b/src/utils/help-json.ts index b85e54a2..b377a912 100644 --- a/src/utils/help-json.ts +++ b/src/utils/help-json.ts @@ -184,6 +184,44 @@ const commands: CommandSchema[] = [ }, ], }, + { + name: 'mcp', + description: 'Manage the WorkOS MCP server in coding agents (Claude Code, Codex, Cursor)', + commands: [ + { + name: 'install', + description: 'Add the WorkOS MCP server to detected coding agents', + options: [ + { + name: 'agent', + type: 'array', + description: 'Target specific agent(s): claude-code, codex, cursor', + required: false, + alias: 'a', + hidden: false, + }, + ], + }, + { + name: 'remove', + description: 'Remove the WorkOS MCP server from coding agents', + options: [ + { + name: 'agent', + type: 'array', + description: 'Target specific agent(s): claude-code, codex, cursor', + required: false, + alias: 'a', + hidden: false, + }, + ], + }, + { + name: 'status', + description: 'Show which coding agents have the WorkOS MCP server configured', + }, + ], + }, { name: 'doctor', description: 'Diagnose WorkOS AuthKit integration issues in the current project', From 10bc045c881737504f85136a44b895d5646199d5 Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Thu, 2 Jul 2026 15:38:44 -0700 Subject: [PATCH 2/8] feat: add MCP install onboarding surfaces, doctor check, and telemetry Wire the Phase 1 MCP client library into three onboarding surfaces plus adoption telemetry: - Install-flow consent prompt after the skills step (maybeOfferMcpInstall): human/TTY-only, not-JSON, decline-respecting, and best-effort so it can never fail or wedge `workos install`. - One-time startup banner (maybeShowMcpNotice) nudging `workos mcp install`, behind a shared one-notice-per-run gate (startup-notice-gate.ts) so the telemetry notice and unclaimed warning take precedence. - `workos doctor` MCP section (checkMcp) reporting per-agent status; a warning is derived only for a Cursor entry with an unexpected URL, never for absent MCP. Shared gate state (declined/banner-shown markers, eligibility predicate) lives in src/lib/mcp-notice.ts and persists in the plain prefs store. Review (1 pass): fixed a JSON-mode prompt-suppression gap so `install --json` on a TTY stays machine-clean. Known limitation: install-flow capture('mcp install') tags don't reach the backend because the installer session ends (runWithCore finally) before the post-install offer runs; tracked for a follow-up session-independent wire event. --- src/bin.ts | 30 +++ src/commands/install.spec.ts | 17 ++ src/commands/install.ts | 5 + src/doctor/checks/mcp.spec.ts | 107 +++++++++++ src/doctor/checks/mcp.ts | 38 ++++ src/doctor/index.ts | 8 +- src/doctor/issues.spec.ts | 41 +++++ src/doctor/issues.ts | 17 ++ src/doctor/output.ts | 15 ++ src/doctor/types.ts | 19 ++ src/lib/mcp-clients.ts | 23 +++ src/lib/mcp-notice.spec.ts | 328 +++++++++++++++++++++++++++++++++ src/lib/mcp-notice.ts | 238 ++++++++++++++++++++++++ src/lib/preferences.ts | 17 ++ src/lib/startup-notice-gate.ts | 32 ++++ src/lib/telemetry-notice.ts | 3 + src/lib/unclaimed-warning.ts | 3 + 17 files changed, 940 insertions(+), 1 deletion(-) create mode 100644 src/doctor/checks/mcp.spec.ts create mode 100644 src/doctor/checks/mcp.ts create mode 100644 src/lib/mcp-notice.spec.ts create mode 100644 src/lib/mcp-notice.ts create mode 100644 src/lib/startup-notice-gate.ts diff --git a/src/bin.ts b/src/bin.ts index 7b7ee6a8..2312ba09 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -323,6 +323,36 @@ async function runCli(): Promise { await applyInsecureStorage(argv.insecureStorage as boolean | undefined); await maybeWarnUnclaimed(); }) + .middleware(async (argv) => { + // One-time MCP banner (lowest-priority startup notice — runs after the + // telemetry notice + unclaimed warning so they win the one-per-run slot). + // Skip commands that manage MCP/agents directly or where the nudge is + // noise, mirroring + extending maybeWarnUnclaimed's list. Self-guarded and + // never throws. + const command = String(argv._?.[0] ?? ''); + if ( + [ + 'mcp', + 'install', + 'doctor', + 'skills', + 'auth', + 'env', + 'claim', + 'debug', + 'dashboard', + 'emulate', + 'dev', + 'migrations', + 'telemetry', + 'completion', + '', + ].includes(command) + ) + return; + const { maybeShowMcpNotice } = await import('./lib/mcp-notice.js'); + await maybeShowMcpNotice(); + }) .command('auth', 'Manage authentication (login, logout, status)', (yargs) => { yargs.options(insecureStorageOption); registerSubcommand( diff --git a/src/commands/install.spec.ts b/src/commands/install.spec.ts index 52848383..df19b169 100644 --- a/src/commands/install.spec.ts +++ b/src/commands/install.spec.ts @@ -8,6 +8,10 @@ vi.mock('./install-skill.js', () => ({ autoInstallSkills: vi.fn(), })); +vi.mock('../lib/mcp-notice.js', () => ({ + maybeOfferMcpInstall: vi.fn(), +})); + vi.mock('../utils/clack.js', () => ({ default: { log: { info: vi.fn(), error: vi.fn() }, @@ -25,6 +29,7 @@ vi.mock('../utils/debug.js', () => ({ const { runInstaller } = await import('../run.js'); const { autoInstallSkills } = await import('./install-skill.js'); +const { maybeOfferMcpInstall } = await import('../lib/mcp-notice.js'); const clack = (await import('../utils/clack.js')).default; const { isJsonMode } = await import('../utils/output.js'); const { CliExit } = await import('../utils/cli-exit.js'); @@ -51,6 +56,18 @@ describe('handleInstall', () => { expect(autoInstallOrder).toBeGreaterThan(runInstallerOrder); }); + it('offers the MCP install after skills, on the install-flow entry point', async () => { + vi.mocked(runInstaller).mockResolvedValue(undefined as any); + vi.mocked(autoInstallSkills).mockResolvedValue(null); + + await expect(handleInstall({ _: ['install'], $0: 'workos' } as any)).resolves.toBeUndefined(); + + expect(maybeOfferMcpInstall).toHaveBeenCalledWith({ entryPoint: 'install-flow' }); + const autoInstallOrder = vi.mocked(autoInstallSkills).mock.invocationCallOrder[0]; + const mcpOfferOrder = vi.mocked(maybeOfferMcpInstall).mock.invocationCallOrder[0]; + expect(mcpOfferOrder).toBeGreaterThan(autoInstallOrder); + }); + it('prints an info line when skills were installed in a TTY session', async () => { vi.mocked(runInstaller).mockResolvedValue(undefined as any); vi.mocked(autoInstallSkills).mockResolvedValue({ diff --git a/src/commands/install.ts b/src/commands/install.ts index b04677eb..cc538be6 100644 --- a/src/commands/install.ts +++ b/src/commands/install.ts @@ -5,6 +5,7 @@ import { exitWithError, isJsonMode } from '../utils/output.js'; import { ExitCode, exitWithCode } from '../utils/exit-codes.js'; import type { ArgumentsCamelCase } from 'yargs'; import { autoInstallSkills } from './install-skill.js'; +import { maybeOfferMcpInstall } from '../lib/mcp-notice.js'; /** * Handle install command execution. @@ -37,6 +38,10 @@ export async function handleInstall(argv: ArgumentsCamelCase): Pr `Installed ${skillResult.skills.length} WorkOS ${skillWord} for ${skillResult.agents.join(', ')}. Your coding agent now has up-to-date WorkOS guidance.`, ); } + + // Offer to connect the user's coding agent to WorkOS via MCP. Self-gating + // (human/TTY-only, decline-respecting) and best-effort — never fails install. + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); } catch (err) { const { getLogFilePath } = await import('../utils/debug.js'); const logPath = getLogFilePath(); diff --git a/src/doctor/checks/mcp.spec.ts b/src/doctor/checks/mcp.spec.ts new file mode 100644 index 00000000..a59d0a1f --- /dev/null +++ b/src/doctor/checks/mcp.spec.ts @@ -0,0 +1,107 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; + +let detectResult: unknown[] = []; +let cursorUrl: string | null = null; + +const detectMcpClientsMock = vi.fn(() => Promise.resolve(detectResult)); +const getCursorConfiguredUrlMock = vi.fn(() => Promise.resolve(cursorUrl)); +vi.mock('../../lib/mcp-clients.js', () => ({ + detectMcpClients: (...a: unknown[]) => detectMcpClientsMock(...(a as [])), + getCursorConfiguredUrl: (...a: unknown[]) => getCursorConfiguredUrlMock(...(a as [])), +})); + +const { MCP_SERVER_URL } = await import('../../lib/constants.js'); +const { checkMcp } = await import('./mcp.js'); + +function fakeClient(key: string, displayName: string, installed: boolean) { + return { + key, + displayName, + isAvailable: vi.fn(() => Promise.resolve(true)), + isInstalled: vi.fn(() => Promise.resolve(installed)), + add: vi.fn(), + remove: vi.fn(), + }; +} + +beforeEach(() => { + vi.clearAllMocks(); + detectResult = []; + cursorUrl = null; + detectMcpClientsMock.mockImplementation(() => Promise.resolve(detectResult)); + getCursorConfiguredUrlMock.mockImplementation(() => Promise.resolve(cursorUrl)); +}); + +describe('checkMcp', () => { + it('returns null when no coding agents are detected', async () => { + detectResult = []; + expect(await checkMcp()).toBeNull(); + }); + + it('reports available + installed per detected agent, with the server URL', async () => { + detectResult = [fakeClient('claude-code', 'Claude Code', true), fakeClient('codex', 'Codex', false)]; + + const result = await checkMcp(); + + expect(result).toEqual({ + serverUrl: MCP_SERVER_URL, + agents: [ + { agent: 'Claude Code', available: true, installed: true }, + { agent: 'Codex', available: true, installed: false }, + ], + }); + }); + + it('flags a Cursor entry with an unexpected URL as misconfigured', async () => { + detectResult = [fakeClient('cursor', 'Cursor', true)]; + cursorUrl = 'https://evil.example.com/mcp'; + + const result = await checkMcp(); + + expect(result!.agents[0]).toEqual({ agent: 'Cursor', available: true, installed: true, misconfigured: true }); + }); + + it('does not flag Cursor when the configured URL matches', async () => { + detectResult = [fakeClient('cursor', 'Cursor', true)]; + cursorUrl = MCP_SERVER_URL; + + const result = await checkMcp(); + + expect(result!.agents[0].misconfigured).toBe(false); + }); + + it('does not flag Cursor when the URL cannot be read (null)', async () => { + detectResult = [fakeClient('cursor', 'Cursor', true)]; + cursorUrl = null; + + const result = await checkMcp(); + + expect(result!.agents[0].misconfigured).toBe(false); + }); + + it('never reads the URL (nor flags) when Cursor lacks the server', async () => { + detectResult = [fakeClient('cursor', 'Cursor', false)]; + + const result = await checkMcp(); + + expect(result!.agents[0].misconfigured).toBeUndefined(); + expect(getCursorConfiguredUrlMock).not.toHaveBeenCalled(); + }); + + it('handles the mixed matrix: one installed, one missing, one misconfigured', async () => { + detectResult = [ + fakeClient('claude-code', 'Claude Code', true), + fakeClient('codex', 'Codex', false), + fakeClient('cursor', 'Cursor', true), + ]; + cursorUrl = 'https://stale.example.com/mcp'; + + const result = await checkMcp(); + + expect(result!.agents).toEqual([ + { agent: 'Claude Code', available: true, installed: true }, + { agent: 'Codex', available: true, installed: false }, + { agent: 'Cursor', available: true, installed: true, misconfigured: true }, + ]); + }); +}); diff --git a/src/doctor/checks/mcp.ts b/src/doctor/checks/mcp.ts new file mode 100644 index 00000000..84f438e2 --- /dev/null +++ b/src/doctor/checks/mcp.ts @@ -0,0 +1,38 @@ +import { detectMcpClients, getCursorConfiguredUrl } from '../../lib/mcp-clients.js'; +import { MCP_SERVER_URL } from '../../lib/constants.js'; +import type { McpInfo, McpAgentMcpStatus } from '../types.js'; + +/** + * Report the WorkOS MCP server status across detected coding agents. + * + * Mirrors checkSkills: per-detected-agent loop, typed `*Info` return, null when + * no agents are detected (so doctor renders no MCP section for users with no + * coding agent installed). Report-only — never mutates config (`--fix` does not + * touch MCP in this phase). + * + * Absent MCP is deliberately NOT an issue: the user may have declined the + * offer. Only Cursor exposes a readable config, so URL drift ("misconfigured") + * is detected for Cursor alone; issues.ts derives a warning from it. Per-agent + * shell-outs carry the 10s timeout from the client library, keeping doctor fast. + */ +export async function checkMcp(): Promise { + const clients = await detectMcpClients(); + if (clients.length === 0) return null; + + const agents = await Promise.all( + clients.map(async (client): Promise => { + const installed = await client.isInstalled(); + const status: McpAgentMcpStatus = { agent: client.displayName, available: true, installed }; + // Cursor is the only client whose config we can read, so it's the only + // one we can flag for URL drift. A missing/unreadable URL (null) is not + // "unexpected" — only a present-but-different URL counts. + if (client.key === 'cursor' && installed) { + const url = await getCursorConfiguredUrl(); + status.misconfigured = url !== null && url !== MCP_SERVER_URL; + } + return status; + }), + ); + + return { serverUrl: MCP_SERVER_URL, agents }; +} diff --git a/src/doctor/index.ts b/src/doctor/index.ts index 5ff26d9a..985d1fa5 100644 --- a/src/doctor/index.ts +++ b/src/doctor/index.ts @@ -9,6 +9,7 @@ import { checkDashboardSettings, compareRedirectUris } from './checks/dashboard. import { checkAuthPatterns } from './checks/auth-patterns.js'; import { checkAiAnalysis } from './checks/ai-analysis.js'; import { checkSkills } from './checks/skills.js'; +import { checkMcp } from './checks/mcp.js'; import { refreshWorkOSSkills } from '../commands/install-skill.js'; import { detectIssues } from './issues.js'; import { formatReport } from './output.js'; @@ -74,14 +75,17 @@ export async function runDoctor(options: DoctorOptions): Promise { const { info: environment, raw: envRaw } = checkEnvironment(options); // Run remaining checks concurrently - const [sdk, framework, runtime, connectivity, language, hostExecution] = await Promise.all([ + const [sdk, framework, runtime, connectivity, language, hostExecution, mcpResult] = await Promise.all([ checkSdk(options), checkFramework(options), checkRuntime(options), checkConnectivity(options, environment.baseUrl ?? 'https://api.workos.com'), checkLanguage(options.installDir), checkHostExecution(), + checkMcp(), ]); + // Normalize the check's null (no agents detected) to undefined for the report. + const mcp = mcpResult ?? undefined; let skills = (await checkSkills()) ?? undefined; @@ -108,6 +112,7 @@ export async function runDoctor(options: DoctorOptions): Promise { hostExecution, connectivity, skills, + mcp, }); const [dashboardResult, authPatterns, aiAnalysis] = await Promise.all([ @@ -156,6 +161,7 @@ export async function runDoctor(options: DoctorOptions): Promise { aiAnalysis, skills, skillsRefresh, + mcp, }; // Detect issues based on (post-refresh) data. diff --git a/src/doctor/issues.spec.ts b/src/doctor/issues.spec.ts index 74c29f1e..f3a9f498 100644 --- a/src/doctor/issues.spec.ts +++ b/src/doctor/issues.spec.ts @@ -61,4 +61,45 @@ describe('detectIssues', () => { }), ); }); + + describe('MCP', () => { + it('adds no issue when MCP is absent or merely not installed', () => { + const report = baseReport(); + // No mcp field at all. + expect(detectIssues(report).some((i) => i.code === 'MCP_MISCONFIGURED')).toBe(false); + + // Detected agents, none misconfigured (some simply lack the server). + report.mcp = { + serverUrl: 'https://mcp.workos.com/mcp', + agents: [ + { agent: 'Claude Code', available: true, installed: false }, + { agent: 'Cursor', available: true, installed: true, misconfigured: false }, + ], + }; + expect(detectIssues(report).some((i) => i.code === 'MCP_MISCONFIGURED')).toBe(false); + }); + + it('adds exactly one warning listing the misconfigured agents', () => { + const report = baseReport(); + report.mcp = { + serverUrl: 'https://mcp.workos.com/mcp', + agents: [ + { agent: 'Claude Code', available: true, installed: true }, + { agent: 'Cursor', available: true, installed: true, misconfigured: true }, + ], + }; + + const mcpIssues = detectIssues(report).filter((i) => i.code === 'MCP_MISCONFIGURED'); + + expect(mcpIssues).toHaveLength(1); + expect(mcpIssues[0]).toEqual( + expect.objectContaining({ + code: 'MCP_MISCONFIGURED', + severity: 'warning', + message: expect.stringContaining('Cursor'), + remediation: 'Run: workos mcp install', + }), + ); + }); + }); }); diff --git a/src/doctor/issues.ts b/src/doctor/issues.ts index d2781e7d..6cce23be 100644 --- a/src/doctor/issues.ts +++ b/src/doctor/issues.ts @@ -178,6 +178,23 @@ export function detectIssues(report: Omit): } } + // MCP server URL drift — warn ONLY when a configured entry points at an + // unexpected URL. Absent MCP is never an issue: the user may have declined + // the offer, and doctor reports state without judging. + if (report.mcp) { + const misconfigured = report.mcp.agents.filter((a) => a.misconfigured); + if (misconfigured.length > 0) { + const agentList = misconfigured.map((a) => a.agent).join(', '); + issues.push({ + code: 'MCP_MISCONFIGURED', + severity: 'warning', + message: `WorkOS MCP server configured with an unexpected URL for ${agentList} — expected ${report.mcp.serverUrl}`, + remediation: 'Run: workos mcp install', + details: { agents: misconfigured.map((a) => a.agent), expectedUrl: report.mcp.serverUrl }, + }); + } + } + return issues; } diff --git a/src/doctor/output.ts b/src/doctor/output.ts index 49532ec3..973b5820 100644 --- a/src/doctor/output.ts +++ b/src/doctor/output.ts @@ -195,6 +195,21 @@ export function formatReport(report: DoctorReport, options?: FormatOptions): voi } } + // MCP Server (per detected coding agent) + if (report.mcp) { + console.log(''); + console.log('MCP Server'); + for (const agent of report.mcp.agents) { + if (agent.misconfigured) { + console.log(` ${Chalk.yellow('!')} ${agent.agent}: configured with an unexpected URL`); + } else if (agent.installed) { + console.log(` ${Chalk.green('✓')} ${agent.agent}: installed`); + } else { + console.log(` ${agent.agent}: ${Chalk.dim('not installed')}`); + } + } + } + // Verbose mode additions if (options?.verbose) { console.log(''); diff --git a/src/doctor/types.ts b/src/doctor/types.ts index c27b267c..07654117 100644 --- a/src/doctor/types.ts +++ b/src/doctor/types.ts @@ -150,6 +150,23 @@ export interface SkillsRefreshResult { skillsInstalled: string[]; } +export interface McpAgentMcpStatus { + /** Display name of the agent (e.g. "Cursor"), mirroring SkillAgentStatus. */ + agent: string; + /** Agent is usable on this machine. */ + available: boolean; + /** The WorkOS MCP server is present in this agent's config. */ + installed: boolean; + /** Cursor only: the entry exists but points at an unexpected URL. */ + misconfigured?: boolean; +} + +export interface McpInfo { + /** The URL the WorkOS MCP server should be configured with. */ + serverUrl: string; + agents: McpAgentMcpStatus[]; +} + export interface DoctorReport { version: string; timestamp: string; @@ -174,6 +191,8 @@ export interface DoctorReport { skills?: SkillsInfo; /** Present only when `--fix` actually performed a refresh. */ skillsRefresh?: SkillsRefreshResult; + /** MCP server status per detected coding agent. Null (absent) when none detected. */ + mcp?: McpInfo; issues: Issue[]; summary: { errors: number; diff --git a/src/lib/mcp-clients.ts b/src/lib/mcp-clients.ts index 7dd091e6..fb764f2c 100644 --- a/src/lib/mcp-clients.ts +++ b/src/lib/mcp-clients.ts @@ -297,6 +297,29 @@ export function createMcpClients(): McpClientTarget[] { return [createClaudeCodeClient(), createCodexClient(), createCursorClient()]; } +/** + * The URL the WorkOS server is configured with in Cursor's `~/.cursor/mcp.json`, + * or null when the file/entry is absent, unreadable, or unparseable. + * + * Cursor is the only client whose config we read directly (the CLI clients don't + * expose per-entry URLs), so this powers doctor's URL-drift ("misconfigured") + * check without a second jsonc reader duplicating the config schema. Read-only + * and never throws — a problem reading just yields null. + */ +export async function getCursorConfiguredUrl(): Promise { + try { + const path = join(homedir(), '.cursor', 'mcp.json'); + if (!(await pathExists(path))) return null; + const content = await readFile(path, 'utf8'); + const parsed = jsonc.parse(content, [], JSONC_PARSE_OPTIONS) as Record | undefined; + const servers = parsed?.mcpServers as Record | undefined; + const entry = servers?.[MCP_SERVER_NAME] as { url?: unknown } | undefined; + return typeof entry?.url === 'string' ? entry.url : null; + } catch { + return null; + } +} + /** * Return only the clients available on this machine, optionally narrowed to * `agentFilter` keys. Availability is probed in parallel. An unknown filter key diff --git a/src/lib/mcp-notice.spec.ts b/src/lib/mcp-notice.spec.ts new file mode 100644 index 00000000..4ea1be5b --- /dev/null +++ b/src/lib/mcp-notice.spec.ts @@ -0,0 +1,328 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import type { McpClientResult } from './mcp-clients.js'; + +// --- Controllable module state (read lazily inside mock factories) --- +let prefs: Record = {}; +let promptAllowed = true; +let humanMode = true; +let jsonMode = false; +let detectResult: unknown[] = []; + +const loadPreferencesMock = vi.fn(() => Promise.resolve(prefs)); +const savePreferencesMock = vi.fn(); +vi.mock('./preferences.js', () => ({ + loadPreferences: (...a: unknown[]) => loadPreferencesMock(...(a as [])), + savePreferences: (...a: unknown[]) => savePreferencesMock(...(a as [])), +})); + +vi.mock('../utils/interaction-mode.js', () => ({ + isPromptAllowed: () => promptAllowed, + isHumanMode: () => humanMode, +})); + +vi.mock('../utils/output.js', () => ({ isJsonMode: () => jsonMode })); + +const mockRenderStderrBox = vi.fn(); +vi.mock('../utils/box.js', () => ({ + renderStderrBox: (...a: unknown[]) => mockRenderStderrBox(...(a as [])), +})); + +const detectMcpClientsMock = vi.fn(() => Promise.resolve(detectResult)); +vi.mock('./mcp-clients.js', () => ({ + detectMcpClients: (...a: unknown[]) => detectMcpClientsMock(...(a as [])), +})); + +const confirmMock = vi.fn(); +const isCancelMock = vi.fn(() => false); +const clackLog = { success: vi.fn(), error: vi.fn(), info: vi.fn() }; +vi.mock('../utils/clack.js', () => ({ + default: { + confirm: (...a: unknown[]) => confirmMock(...(a as [])), + isCancel: (...a: unknown[]) => isCancelMock(...(a as [])), + log: clackLog, + }, +})); + +const captureMock = vi.fn(); +vi.mock('../utils/analytics.js', () => ({ analytics: { capture: (...a: unknown[]) => captureMock(...(a as [])) } })); + +const { + getMcpAskState, + recordMcpDeclined, + recordMcpBannerShown, + isAutoAskEligible, + maybeShowMcpNotice, + maybeOfferMcpInstall, + resetMcpNoticeState, +} = await import('./mcp-notice.js'); +const { markStartupNoticeShown, resetStartupNoticeGate } = await import('./startup-notice-gate.js'); + +interface FakeClientOpts { + installed?: boolean; + add?: McpClientResult; + addThrows?: boolean; +} +function fakeClient(key: string, displayName: string, opts: FakeClientOpts = {}) { + return { + key, + displayName, + isAvailable: vi.fn(() => Promise.resolve(true)), + isInstalled: vi.fn(() => Promise.resolve(opts.installed ?? false)), + add: vi.fn(() => + opts.addThrows + ? Promise.reject(new Error('add exploded')) + : Promise.resolve(opts.add ?? ({ agent: key, displayName, outcome: 'installed' } as McpClientResult)), + ), + remove: vi.fn(), + }; +} + +beforeEach(() => { + vi.clearAllMocks(); + prefs = {}; + promptAllowed = true; + humanMode = true; + jsonMode = false; + detectResult = []; + loadPreferencesMock.mockImplementation(() => Promise.resolve(prefs)); + detectMcpClientsMock.mockImplementation(() => Promise.resolve(detectResult)); + savePreferencesMock.mockReset(); + confirmMock.mockReset(); + isCancelMock.mockReturnValue(false); + resetMcpNoticeState(); + resetStartupNoticeGate(); +}); + +describe('getMcpAskState', () => { + it('reads declined + bannerShown from prefs', async () => { + prefs = { mcp: { promptDeclined: true, bannerShownAt: '2026-01-01T00:00:00.000Z' } }; + expect(await getMcpAskState()).toEqual({ declined: true, bannerShown: true }); + }); + + it('defaults to false when no mcp prefs exist', async () => { + prefs = {}; + expect(await getMcpAskState()).toEqual({ declined: false, bannerShown: false }); + }); + + it('degrades to false/false when loadPreferences throws', async () => { + loadPreferencesMock.mockRejectedValueOnce(new Error('EIO')); + expect(await getMcpAskState()).toEqual({ declined: false, bannerShown: false }); + }); +}); + +describe('markers', () => { + it('recordMcpDeclined persists promptDeclined', async () => { + await recordMcpDeclined(); + expect(savePreferencesMock).toHaveBeenCalledWith({ mcp: { promptDeclined: true } }); + }); + + it('recordMcpBannerShown persists a bannerShownAt timestamp', async () => { + await recordMcpBannerShown(); + expect(savePreferencesMock).toHaveBeenCalledWith({ mcp: { bannerShownAt: expect.any(String) } }); + }); + + it('swallows prefs write failures (degrades to per-run memory)', async () => { + savePreferencesMock.mockImplementation(() => { + throw new Error('EROFS'); + }); + await expect(recordMcpDeclined()).resolves.toBeUndefined(); + await expect(recordMcpBannerShown()).resolves.toBeUndefined(); + }); +}); + +describe('isAutoAskEligible', () => { + it('false when declined — and never shells out to detect clients', async () => { + prefs = { mcp: { promptDeclined: true } }; + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + expect(await isAutoAskEligible()).toBe(false); + expect(detectMcpClientsMock).not.toHaveBeenCalled(); + }); + + it('false when no agents are detected', async () => { + detectResult = []; + expect(await isAutoAskEligible()).toBe(false); + }); + + it('false when every detected agent already has the server', async () => { + detectResult = [fakeClient('cursor', 'Cursor', { installed: true })]; + expect(await isAutoAskEligible()).toBe(false); + }); + + it('true when at least one detected agent lacks the server', async () => { + detectResult = [ + fakeClient('claude-code', 'Claude Code', { installed: true }), + fakeClient('cursor', 'Cursor', { installed: false }), + ]; + expect(await isAutoAskEligible()).toBe(true); + }); +}); + +describe('maybeShowMcpNotice (banner)', () => { + it('renders once and records bannerShown when eligible in human mode', async () => { + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).toHaveBeenCalledTimes(1); + expect(savePreferencesMock).toHaveBeenCalledWith({ mcp: { bannerShownAt: expect.any(String) } }); + }); + + it('does not render a second time in the same session', async () => { + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).toHaveBeenCalledTimes(1); + }); + + it('suppressed outside human mode', async () => { + humanMode = false; + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).not.toHaveBeenCalled(); + }); + + it('suppressed in JSON mode', async () => { + jsonMode = true; + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).not.toHaveBeenCalled(); + }); + + it('defers when another startup notice already fired this run', async () => { + markStartupNoticeShown(); // e.g. the telemetry notice or unclaimed warning won + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).not.toHaveBeenCalled(); + }); + + it('suppressed when the banner was already shown on a previous run', async () => { + prefs = { mcp: { bannerShownAt: '2025-01-01T00:00:00.000Z' } }; + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).not.toHaveBeenCalled(); + }); + + it('suppressed for a declined user', async () => { + prefs = { mcp: { promptDeclined: true } }; + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).not.toHaveBeenCalled(); + }); + + it('suppressed when nothing is installable (all agents already have it)', async () => { + detectResult = [fakeClient('cursor', 'Cursor', { installed: true })]; + await maybeShowMcpNotice(); + expect(mockRenderStderrBox).not.toHaveBeenCalled(); + }); +}); + +describe('maybeOfferMcpInstall (install-flow prompt)', () => { + it('never prompts when prompting is not allowed (agent/CI/non-TTY)', async () => { + promptAllowed = false; + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + expect(confirmMock).not.toHaveBeenCalled(); + expect(captureMock).not.toHaveBeenCalled(); + expect(savePreferencesMock).not.toHaveBeenCalled(); + }); + + it('never prompts in JSON mode (e.g. `install --json` on a TTY) so output stays clean', async () => { + jsonMode = true; // human interaction mode but machine-readable output + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + expect(confirmMock).not.toHaveBeenCalled(); + expect(captureMock).not.toHaveBeenCalled(); + }); + + it('installs to detected-and-missing agents on accept and captures the outcome', async () => { + const claude = fakeClient('claude-code', 'Claude Code', { installed: false }); + const cursor = fakeClient('cursor', 'Cursor', { installed: true }); // already has it → not a target + detectResult = [claude, cursor]; + confirmMock.mockResolvedValue(true); + + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + + // Prompt names only the installable agent. + const message = confirmMock.mock.calls[0][0].message as string; + expect(message).toContain('Claude Code'); + expect(message).not.toContain('Cursor'); + + expect(claude.add).toHaveBeenCalledTimes(1); + expect(cursor.add).not.toHaveBeenCalled(); + expect(captureMock).toHaveBeenCalledWith('mcp install', { + entry_point: 'install-flow', + accepted: true, + agents_installed: 'claude-code', + agents_failed: '', + }); + }); + + it('records the decline and captures accepted:false on explicit no', async () => { + const cursor = fakeClient('cursor', 'Cursor', { installed: false }); + detectResult = [cursor]; + confirmMock.mockResolvedValue(false); + + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + + expect(savePreferencesMock).toHaveBeenCalledWith({ mcp: { promptDeclined: true } }); + expect(cursor.add).not.toHaveBeenCalled(); + expect(captureMock).toHaveBeenCalledWith('mcp install', { + entry_point: 'install-flow', + accepted: false, + agents_installed: '', + agents_failed: '', + }); + }); + + it('treats ctrl-C (cancel) as neither a decline nor an install', async () => { + const cursor = fakeClient('cursor', 'Cursor', { installed: false }); + detectResult = [cursor]; + confirmMock.mockResolvedValue(Symbol('cancel')); + isCancelMock.mockReturnValue(true); + + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + + expect(savePreferencesMock).not.toHaveBeenCalled(); + expect(captureMock).not.toHaveBeenCalled(); + expect(cursor.add).not.toHaveBeenCalled(); + }); + + it('does not prompt a user who already declined', async () => { + prefs = { mcp: { promptDeclined: true } }; + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + expect(confirmMock).not.toHaveBeenCalled(); + }); + + it('does not prompt when there is nothing to install', async () => { + detectResult = [fakeClient('cursor', 'Cursor', { installed: true })]; + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + expect(confirmMock).not.toHaveBeenCalled(); + }); + + it('never throws even if a client install throws (install flow unaffected)', async () => { + detectResult = [fakeClient('cursor', 'Cursor', { installed: false, addThrows: true })]; + confirmMock.mockResolvedValue(true); + await expect(maybeOfferMcpInstall({ entryPoint: 'install-flow' })).resolves.toBeUndefined(); + }); + + it('reports both installed and failed agents in the capture', async () => { + const ok = fakeClient('claude-code', 'Claude Code', { + installed: false, + add: { agent: 'claude-code', displayName: 'Claude Code', outcome: 'installed' }, + }); + const bad = fakeClient('cursor', 'Cursor', { + installed: false, + add: { agent: 'cursor', displayName: 'Cursor', outcome: 'failed', error: 'nope' }, + }); + detectResult = [ok, bad]; + confirmMock.mockResolvedValue(true); + + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + + expect(captureMock).toHaveBeenCalledWith('mcp install', { + entry_point: 'install-flow', + accepted: true, + agents_installed: 'claude-code', + agents_failed: 'cursor', + }); + }); +}); diff --git a/src/lib/mcp-notice.ts b/src/lib/mcp-notice.ts new file mode 100644 index 00000000..11b35d75 --- /dev/null +++ b/src/lib/mcp-notice.ts @@ -0,0 +1,238 @@ +/** + * MCP-install onboarding surfaces + their shared gate state. + * + * One module owns all automatic-ask state so the install-flow prompt and the + * one-time banner can't drift apart. The decline contract is absolute: any + * explicit "no" records `promptDeclined` and no automatic surface ever asks + * again — `workos mcp install` stays available manually. + * + * Mirrors telemetry-notice.ts: persisted shown/declined state in the plain + * prefs store, mode-gated display, and a never-throws contract so a notice can + * never block or fail a command. The mode gate is the CLI's interaction-mode + * system (isPromptAllowed / isHumanMode), which already folds in CI markers, + * agent markers, and TTY state — non-TTY safety comes from using it. + */ + +import chalk from 'chalk'; +import clack from '../utils/clack.js'; +import { isHumanMode, isPromptAllowed } from '../utils/interaction-mode.js'; +import { isJsonMode } from '../utils/output.js'; +import { renderStderrBox } from '../utils/box.js'; +import { formatWorkOSCommand } from '../utils/command-invocation.js'; +import { analytics } from '../utils/analytics.js'; +import { loadPreferences, savePreferences } from './preferences.js'; +import { detectMcpClients, type McpClientResult, type McpClientTarget } from './mcp-clients.js'; +import { hasStartupNoticeShown, markStartupNoticeShown } from './startup-notice-gate.js'; + +export type McpAskState = { declined: boolean; bannerShown: boolean }; + +/** + * Best-effort ceiling on the whole install-flow offer so a wedged prompt can + * never hold up `workos install`. Mirrors login.ts's SKILL_INSTALL_TIMEOUT_MS. + */ +export const MCP_OFFER_TIMEOUT_MS = 30 * 1000; + +let bannerShownThisSession = false; + +/** Human phrasing for each install outcome shown in the accept matrix. */ +const OUTCOME_LABEL: Record = { + installed: 'installed', + 'already-installed': 'already installed', + removed: 'removed', + 'not-installed': 'not installed', + skipped: 'skipped', + failed: 'failed', +}; + +/** + * Read the persisted automatic-ask state. Never throws — a missing/corrupt + * prefs file degrades to "nothing recorded" so gating still works in-memory. + */ +export async function getMcpAskState(): Promise { + try { + const prefs = await loadPreferences(); + return { + declined: prefs.mcp?.promptDeclined === true, + bannerShown: Boolean(prefs.mcp?.bannerShownAt), + }; + } catch { + return { declined: false, bannerShown: false }; + } +} + +/** + * Record an explicit decline. Absolute and permanent for automatic surfaces. + * Write failures are swallowed: gating degrades to per-run memory, never + * crashes a command. + */ +export async function recordMcpDeclined(): Promise { + try { + savePreferences({ mcp: { promptDeclined: true } }); + } catch { + // Swallow — a read-only prefs file must never break a command. + } +} + +/** Record that the one-time banner was shown, stamping the current time. */ +export async function recordMcpBannerShown(): Promise { + try { + savePreferences({ mcp: { bannerShownAt: new Date().toISOString() } }); + } catch { + // Swallow — see recordMcpDeclined. + } +} + +/** + * The detected agents that would actually receive an install: available on this + * machine AND missing the WorkOS server. Empty when there is nothing to offer. + * Never throws — detection failure yields an empty set. + */ +async function detectInstallTargets(): Promise { + try { + const clients = await detectMcpClients(); + if (clients.length === 0) return []; + const installed = await Promise.all(clients.map((c) => c.isInstalled())); + return clients.filter((_, i) => !installed[i]); + } catch { + return []; + } +} + +/** + * Would an automatic ask be appropriate right now? True only when the user has + * not declined AND at least one detected agent lacks the server. Does NOT gate + * on interaction mode — callers add that (isPromptAllowed for the prompt, + * isHumanMode for the banner). Checks `declined` first so declined machines + * never pay for the client shell-outs. + */ +export async function isAutoAskEligible(): Promise { + const { declined } = await getMcpAskState(); + if (declined) return false; + const targets = await detectInstallTargets(); + return targets.length > 0; +} + +/** + * One-time stderr banner nudging the user toward `workos mcp install`. Shown at + * most once per machine, only on a normal human-mode run, and never when an + * earlier startup notice already fired this run (telemetry notice and unclaimed + * warning take precedence). Records `bannerShownAt` before printing — + * shown-once beats seen-once (a lost banner is fine; a nag loop is not). Never + * throws. + */ +export async function maybeShowMcpNotice(): Promise { + try { + if (bannerShownThisSession) return; + if (!isHumanMode()) return; // suppress in agent / CI / non-TTY + if (isJsonMode()) return; // never on the machine-readable path + if (hasStartupNoticeShown()) return; // one-notice-per-run cap; telemetry/unclaimed win + const { bannerShown } = await getMcpAskState(); + if (bannerShown) return; // already shown once, ever + if (!(await isAutoAskEligible())) return; // declined, or nothing to offer + + // Claim the slot + persist BEFORE printing: a lost banner beats a nag loop. + bannerShownThisSession = true; + markStartupNoticeShown(); + await recordMcpBannerShown(); + + const cmd = chalk.cyan(formatWorkOSCommand('mcp install')); + const inner = ` ${chalk.cyan('ℹ')} New: connect your coding agent to WorkOS. Run ${cmd} to add the WorkOS MCP server (Claude Code, Codex, Cursor). `; + renderStderrBox(inner, chalk.cyan); + } catch { + // Never block command startup. + } +} + +/** Emit the per-agent install matrix (human mode) without ever exiting. */ +function printInstallMatrix(results: McpClientResult[]): void { + for (const r of results) { + const line = `${r.displayName}: ${OUTCOME_LABEL[r.outcome]}`; + if (r.outcome === 'failed') { + clack.log.error(r.error ? `${line} — ${r.error}` : line); + } else { + clack.log.success(line); + } + } +} + +/** + * The real install-flow offer. Self-gating: renders nothing unless prompting is + * allowed, the user hasn't declined, and there is at least one agent to install + * to. On yes: install + print the matrix + capture. On explicit no: record the + * decline + capture (a decline is an adoption signal). On cancel (ctrl-C): skip + * silently without recording — a cancel is not a decline. + */ +async function offerMcpInstall(): Promise { + if (!isPromptAllowed()) return; // the entire mode gate (CI / agent / non-TTY) + if (isJsonMode()) return; // never prompt on the machine-readable path (e.g. `install --json` on a TTY) + const { declined } = await getMcpAskState(); + if (declined) return; // decline is absolute + const targets = await detectInstallTargets(); + if (targets.length === 0) return; // nothing to offer + + const names = targets.map((t) => t.displayName).join(', '); + const answer = await clack.confirm({ + message: `Add the WorkOS MCP server to ${names}? Your coding agent gets tools to manage WorkOS resources (you'll authorize via OAuth on first use).`, + }); + + // Cancel (ctrl-C) is not a decline — skip silently, ask again next time. + if (clack.isCancel(answer)) return; + + if (!answer) { + // Record the decline BEFORE anything else so a later crash can't re-ask. + await recordMcpDeclined(); + analytics.capture('mcp install', { + entry_point: 'install-flow', + accepted: false, + agents_installed: '', + agents_failed: '', + }); + return; + } + + const results: McpClientResult[] = []; + for (const target of targets) { + results.push(await target.add()); + } + printInstallMatrix(results); + + const installed = results + .filter((r) => r.outcome === 'installed' || r.outcome === 'already-installed') + .map((r) => r.agent); + const failed = results.filter((r) => r.outcome === 'failed').map((r) => r.agent); + analytics.capture('mcp install', { + entry_point: 'install-flow', + accepted: true, + agents_installed: installed.join(','), + agents_failed: failed.join(','), + }); +} + +/** + * Offer to install the WorkOS MCP server at the end of `workos install`. + * + * Wraps offerMcpInstall best-effort: a try/catch AND a 30s unref'd-timeout race + * (login.ts pattern) so the offer can never throw into, wedge, or fail the + * install flow. `workos install` has already succeeded by the time this runs. + */ +export async function maybeOfferMcpInstall(_opts: { entryPoint: 'install-flow' }): Promise { + let timeoutHandle: ReturnType | undefined; + try { + const timeout = new Promise((resolve) => { + timeoutHandle = setTimeout(() => resolve(), MCP_OFFER_TIMEOUT_MS); + // Don't keep the event loop alive on this timer — the process should exit + // as soon as everything else settles. + timeoutHandle.unref?.(); + }); + await Promise.race([offerMcpInstall(), timeout]); + } catch { + // The MCP offer must never fail or block `workos install`. + } finally { + if (timeoutHandle) clearTimeout(timeoutHandle); + } +} + +/** Reset per-session banner state (for testing). */ +export function resetMcpNoticeState(): void { + bannerShownThisSession = false; +} diff --git a/src/lib/preferences.ts b/src/lib/preferences.ts index 159df931..5b9c5490 100644 --- a/src/lib/preferences.ts +++ b/src/lib/preferences.ts @@ -24,6 +24,20 @@ export interface CliPreferences { /** ISO timestamp the first-run notice was shown — written in Phase 2 only. */ noticeShownAt?: string; }; + /** + * MCP-install onboarding state. Owned semantically by lib/mcp-notice.ts; the + * shape lives here so it rides the same plain-JSON prefs store as telemetry. + */ + mcp?: { + /** + * true => the user explicitly declined an automatic MCP install offer. The + * decline is absolute: no automatic surface (prompt or banner) asks again; + * `workos mcp install` stays available manually. + */ + promptDeclined?: boolean; + /** ISO timestamp the one-time MCP banner was shown. */ + bannerShownAt?: string; + }; } /** Effective source of the resolved telemetry-enabled decision. */ @@ -117,6 +131,9 @@ export function savePreferences(next: CliPreferences): void { ...current, ...next, ...(current.telemetry || next.telemetry ? { telemetry: { ...current.telemetry, ...next.telemetry } } : {}), + // Deep-merge mcp too so writing one marker (e.g. bannerShownAt) never + // clobbers the other (promptDeclined), which are written at different times. + ...(current.mcp || next.mcp ? { mcp: { ...current.mcp, ...next.mcp } } : {}), }; fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 }); diff --git a/src/lib/startup-notice-gate.ts b/src/lib/startup-notice-gate.ts new file mode 100644 index 00000000..d87e344b --- /dev/null +++ b/src/lib/startup-notice-gate.ts @@ -0,0 +1,32 @@ +/** + * One-notice-per-run coordinator for the startup stderr notices. + * + * Three middlewares can each want to print a one-line stderr notice at startup: + * the first-run telemetry notice, the unclaimed-environment warning, and the + * MCP banner. Stacking two or three boxes on a single command is noise, so this + * module is the shared latch — whichever fires first calls + * markStartupNoticeShown(), and the lower-priority MCP banner checks + * hasStartupNoticeShown() and defers. + * + * Ordering IS priority: bin.ts runs the telemetry + unclaimed middlewares before + * the MCP banner middleware, so those two always win a contested run. In-memory + * only (a run is a single CLI process); the per-machine "already shown" state is + * persisted separately by each notice. + */ + +let shown = false; + +/** Record that a startup notice has displayed this run. */ +export function markStartupNoticeShown(): void { + shown = true; +} + +/** Whether any startup notice has already displayed this run. */ +export function hasStartupNoticeShown(): boolean { + return shown; +} + +/** Reset the latch (for testing). */ +export function resetStartupNoticeGate(): void { + shown = false; +} diff --git a/src/lib/telemetry-notice.ts b/src/lib/telemetry-notice.ts index 17e44e45..74e5981b 100644 --- a/src/lib/telemetry-notice.ts +++ b/src/lib/telemetry-notice.ts @@ -18,6 +18,7 @@ import { isJsonMode } from '../utils/output.js'; import { renderStderrBox } from '../utils/box.js'; import { formatWorkOSCommand } from '../utils/command-invocation.js'; import { isNoticeShown, markNoticeShown, isTelemetryOptedOut } from './preferences.js'; +import { markStartupNoticeShown } from './startup-notice-gate.js'; let shownThisSession = false; @@ -44,6 +45,8 @@ export function maybeShowTelemetryNotice(): void { // rather than silently suppressing the notice for the rest of the session. shownThisSession = true; markNoticeShown(); + // Claim the one-notice-per-run slot so the lower-priority MCP banner defers. + markStartupNoticeShown(); } catch { // Never block command execution. } diff --git a/src/lib/unclaimed-warning.ts b/src/lib/unclaimed-warning.ts index 198fa125..9ce9c033 100644 --- a/src/lib/unclaimed-warning.ts +++ b/src/lib/unclaimed-warning.ts @@ -13,6 +13,7 @@ import { createClaimNonce, UnclaimedEnvApiError } from './unclaimed-env-api.js'; import { logError, logInfo } from '../utils/debug.js'; import { isJsonMode } from '../utils/output.js'; import { renderStderrBox } from '../utils/box.js'; +import { markStartupNoticeShown } from './startup-notice-gate.js'; let warningShownThisSession = false; let claimCheckDoneThisSession = false; @@ -61,6 +62,8 @@ export async function warnIfUnclaimed(): Promise { if (!isJsonMode()) { const inner = ` ${chalk.yellow('⚠ Unclaimed environment')} — Run ${chalk.cyan('workos env claim')} to keep your data. `; renderStderrBox(inner, chalk.yellow); + // Claim the one-notice-per-run slot so the lower-priority MCP banner defers. + markStartupNoticeShown(); } } catch (error) { // Never block command execution, but log for diagnostics From 864f9123f91a4eff007d11b617ed4c1a27d48810 Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Thu, 2 Jul 2026 18:04:56 -0700 Subject: [PATCH 3/8] fix: emit mcp offer adoption telemetry as queued command events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The install-flow prompt and banner previously used analytics.capture(), which only folds props into installer session tags — dead by the time the offer runs, because run-with-core's finally has already shut down analytics and flushed session.end. Queue real 'mcp offer' command events instead, carrying entry_point, accepted, and per-agent outcomes as mcp.* attributes; queued events ride bin.ts's unconditional final flush, with store-forward covering anything the flush misses. The telemetry gateway's command schema is passthrough and flattens custom attributes onto command spans, so no backend change is needed. Also emits a banner impression event, making banner→install conversion directly measurable instead of approximate. --- src/lib/mcp-notice.spec.ts | 80 +++++++++++++++++++++++++++--------- src/lib/mcp-notice.ts | 45 ++++++++++++++------ src/utils/analytics.spec.ts | 22 ++++++++++ src/utils/analytics.ts | 4 ++ src/utils/telemetry-types.ts | 5 ++- 5 files changed, 122 insertions(+), 34 deletions(-) diff --git a/src/lib/mcp-notice.spec.ts b/src/lib/mcp-notice.spec.ts index 4ea1be5b..a9410755 100644 --- a/src/lib/mcp-notice.spec.ts +++ b/src/lib/mcp-notice.spec.ts @@ -44,7 +44,13 @@ vi.mock('../utils/clack.js', () => ({ })); const captureMock = vi.fn(); -vi.mock('../utils/analytics.js', () => ({ analytics: { capture: (...a: unknown[]) => captureMock(...(a as [])) } })); +const emitCommandEventMock = vi.fn(); +vi.mock('../utils/analytics.js', () => ({ + analytics: { + capture: (...a: unknown[]) => captureMock(...(a as [])), + emitCommandEvent: (...a: unknown[]) => emitCommandEventMock(...(a as [])), + }, +})); const { getMcpAskState, @@ -165,11 +171,21 @@ describe('maybeShowMcpNotice (banner)', () => { expect(savePreferencesMock).toHaveBeenCalledWith({ mcp: { bannerShownAt: expect.any(String) } }); }); - it('does not render a second time in the same session', async () => { + it('emits a banner impression event when shown', async () => { + detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; + await maybeShowMcpNotice(); + expect(emitCommandEventMock).toHaveBeenCalledTimes(1); + expect(emitCommandEventMock).toHaveBeenCalledWith('mcp offer', 0, true, { + extraAttributes: { 'mcp.entry_point': 'banner', 'mcp.shown': true }, + }); + }); + + it('does not render or emit a second time in the same session', async () => { detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; await maybeShowMcpNotice(); await maybeShowMcpNotice(); expect(mockRenderStderrBox).toHaveBeenCalledTimes(1); + expect(emitCommandEventMock).toHaveBeenCalledTimes(1); }); it('suppressed outside human mode', async () => { @@ -220,7 +236,7 @@ describe('maybeOfferMcpInstall (install-flow prompt)', () => { detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); expect(confirmMock).not.toHaveBeenCalled(); - expect(captureMock).not.toHaveBeenCalled(); + expect(emitCommandEventMock).not.toHaveBeenCalled(); expect(savePreferencesMock).not.toHaveBeenCalled(); }); @@ -229,7 +245,7 @@ describe('maybeOfferMcpInstall (install-flow prompt)', () => { detectResult = [fakeClient('cursor', 'Cursor', { installed: false })]; await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); expect(confirmMock).not.toHaveBeenCalled(); - expect(captureMock).not.toHaveBeenCalled(); + expect(emitCommandEventMock).not.toHaveBeenCalled(); }); it('installs to detected-and-missing agents on accept and captures the outcome', async () => { @@ -247,11 +263,13 @@ describe('maybeOfferMcpInstall (install-flow prompt)', () => { expect(claude.add).toHaveBeenCalledTimes(1); expect(cursor.add).not.toHaveBeenCalled(); - expect(captureMock).toHaveBeenCalledWith('mcp install', { - entry_point: 'install-flow', - accepted: true, - agents_installed: 'claude-code', - agents_failed: '', + expect(emitCommandEventMock).toHaveBeenCalledWith('mcp offer', expect.any(Number), true, { + extraAttributes: { + 'mcp.entry_point': 'install-flow', + 'mcp.accepted': true, + 'mcp.agents_installed': 'claude-code', + 'mcp.agents_failed': '', + }, }); }); @@ -264,11 +282,14 @@ describe('maybeOfferMcpInstall (install-flow prompt)', () => { expect(savePreferencesMock).toHaveBeenCalledWith({ mcp: { promptDeclined: true } }); expect(cursor.add).not.toHaveBeenCalled(); - expect(captureMock).toHaveBeenCalledWith('mcp install', { - entry_point: 'install-flow', - accepted: false, - agents_installed: '', - agents_failed: '', + // A decline is a completed interaction, not an error: success stays true. + expect(emitCommandEventMock).toHaveBeenCalledWith('mcp offer', expect.any(Number), true, { + extraAttributes: { + 'mcp.entry_point': 'install-flow', + 'mcp.accepted': false, + 'mcp.agents_installed': '', + 'mcp.agents_failed': '', + }, }); }); @@ -281,7 +302,7 @@ describe('maybeOfferMcpInstall (install-flow prompt)', () => { await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); expect(savePreferencesMock).not.toHaveBeenCalled(); - expect(captureMock).not.toHaveBeenCalled(); + expect(emitCommandEventMock).not.toHaveBeenCalled(); expect(cursor.add).not.toHaveBeenCalled(); }); @@ -318,11 +339,30 @@ describe('maybeOfferMcpInstall (install-flow prompt)', () => { await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); - expect(captureMock).toHaveBeenCalledWith('mcp install', { - entry_point: 'install-flow', - accepted: true, - agents_installed: 'claude-code', - agents_failed: 'cursor', + // An accepted offer with a failed agent install is an error span: + // success flips to false while the per-agent lists carry the detail. + expect(emitCommandEventMock).toHaveBeenCalledWith('mcp offer', expect.any(Number), false, { + extraAttributes: { + 'mcp.entry_point': 'install-flow', + 'mcp.accepted': true, + 'mcp.agents_installed': 'claude-code', + 'mcp.agents_failed': 'cursor', + }, + }); + }); + + it('counts already-installed agents as installed in the emission', async () => { + const already = fakeClient('codex', 'Codex', { + installed: false, + add: { agent: 'codex', displayName: 'Codex', outcome: 'already-installed' }, + }); + detectResult = [already]; + confirmMock.mockResolvedValue(true); + + await maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + + expect(emitCommandEventMock).toHaveBeenCalledWith('mcp offer', expect.any(Number), true, { + extraAttributes: expect.objectContaining({ 'mcp.agents_installed': 'codex', 'mcp.agents_failed': '' }), }); }); }); diff --git a/src/lib/mcp-notice.ts b/src/lib/mcp-notice.ts index 11b35d75..c5fb9e28 100644 --- a/src/lib/mcp-notice.ts +++ b/src/lib/mcp-notice.ts @@ -135,6 +135,12 @@ export async function maybeShowMcpNotice(): Promise { markStartupNoticeShown(); await recordMcpBannerShown(); + // Impression event. Queued (not capture()d) so it rides the CLI's final + // flush; capture() only folds session tags and no session exists here. + analytics.emitCommandEvent('mcp offer', 0, true, { + extraAttributes: { 'mcp.entry_point': 'banner', 'mcp.shown': true }, + }); + const cmd = chalk.cyan(formatWorkOSCommand('mcp install')); const inner = ` ${chalk.cyan('ℹ')} New: connect your coding agent to WorkOS. Run ${cmd} to add the WorkOS MCP server (Claude Code, Codex, Cursor). `; renderStderrBox(inner, chalk.cyan); @@ -158,9 +164,9 @@ function printInstallMatrix(results: McpClientResult[]): void { /** * The real install-flow offer. Self-gating: renders nothing unless prompting is * allowed, the user hasn't declined, and there is at least one agent to install - * to. On yes: install + print the matrix + capture. On explicit no: record the - * decline + capture (a decline is an adoption signal). On cancel (ctrl-C): skip - * silently without recording — a cancel is not a decline. + * to. On yes: install + print the matrix + emit the adoption event. On explicit + * no: record the decline + emit (a decline is an adoption signal). On cancel + * (ctrl-C): skip silently without recording — a cancel is not a decline. */ async function offerMcpInstall(): Promise { if (!isPromptAllowed()) return; // the entire mode gate (CI / agent / non-TTY) @@ -171,6 +177,7 @@ async function offerMcpInstall(): Promise { if (targets.length === 0) return; // nothing to offer const names = targets.map((t) => t.displayName).join(', '); + const offerStartedAt = Date.now(); const answer = await clack.confirm({ message: `Add the WorkOS MCP server to ${names}? Your coding agent gets tools to manage WorkOS resources (you'll authorize via OAuth on first use).`, }); @@ -178,14 +185,22 @@ async function offerMcpInstall(): Promise { // Cancel (ctrl-C) is not a decline — skip silently, ask again next time. if (clack.isCancel(answer)) return; + // Adoption events are queued command events, NOT capture(): the installer + // session has already shut down by the time this offer runs (run-with-core + // fires session.end in its finally), so folded tags would never ship. A + // queued event rides the CLI's unconditional final flush (bin.ts) and the + // store-forward exit handler covers anything the flush misses. if (!answer) { // Record the decline BEFORE anything else so a later crash can't re-ask. await recordMcpDeclined(); - analytics.capture('mcp install', { - entry_point: 'install-flow', - accepted: false, - agents_installed: '', - agents_failed: '', + // A decline is a completed interaction, not an error: success stays true. + analytics.emitCommandEvent('mcp offer', Date.now() - offerStartedAt, true, { + extraAttributes: { + 'mcp.entry_point': 'install-flow', + 'mcp.accepted': false, + 'mcp.agents_installed': '', + 'mcp.agents_failed': '', + }, }); return; } @@ -200,11 +215,15 @@ async function offerMcpInstall(): Promise { .filter((r) => r.outcome === 'installed' || r.outcome === 'already-installed') .map((r) => r.agent); const failed = results.filter((r) => r.outcome === 'failed').map((r) => r.agent); - analytics.capture('mcp install', { - entry_point: 'install-flow', - accepted: true, - agents_installed: installed.join(','), - agents_failed: failed.join(','), + // success=false when any agent failed, so the offer surfaces as an error + // span while mcp.agents_failed carries which ones. + analytics.emitCommandEvent('mcp offer', Date.now() - offerStartedAt, failed.length === 0, { + extraAttributes: { + 'mcp.entry_point': 'install-flow', + 'mcp.accepted': true, + 'mcp.agents_installed': installed.join(','), + 'mcp.agents_failed': failed.join(','), + }, }); } diff --git a/src/utils/analytics.spec.ts b/src/utils/analytics.spec.ts index af8c8d52..44f682ee 100644 --- a/src/utils/analytics.spec.ts +++ b/src/utils/analytics.spec.ts @@ -596,6 +596,28 @@ describe('Analytics', () => { expect(event.attributes['termination.reason']).toBeUndefined(); expect(event.attributes['api.status']).toBeUndefined(); }); + + it('merges extraAttributes into the event attributes', () => { + analytics.emitCommandEvent('mcp offer', 0, true, { + extraAttributes: { 'mcp.entry_point': 'banner', 'mcp.shown': true }, + }); + + const event = mockQueueEvent.mock.calls.find((c: any) => c[0].type === 'command')[0]; + expect(event.attributes['mcp.entry_point']).toBe('banner'); + expect(event.attributes['mcp.shown']).toBe(true); + expect(event.attributes['command.name']).toBe('mcp offer'); + }); + + it('extraAttributes cannot override standard command fields', () => { + analytics.emitCommandEvent('mcp offer', 5, true, { + extraAttributes: { 'command.name': 'evil', 'command.success': false, 'device.id': 'spoofed' }, + }); + + const event = mockQueueEvent.mock.calls.find((c: any) => c[0].type === 'command')[0]; + expect(event.attributes['command.name']).toBe('mcp offer'); + expect(event.attributes['command.success']).toBe(true); + expect(event.attributes['device.id']).toBe(TEST_DEVICE_ID); + }); }); describe('captureUnhandledCrash', () => { diff --git a/src/utils/analytics.ts b/src/utils/analytics.ts index 1f529375..7ffc71b3 100644 --- a/src/utils/analytics.ts +++ b/src/utils/analytics.ts @@ -295,6 +295,7 @@ export class Analytics { reason?: TerminationReason; errorCode?: string; apiContext?: { status?: number; code?: string; resource?: string }; + extraAttributes?: Record; }, ) { if (!this.isEnabled()) return; @@ -306,6 +307,9 @@ export class Analytics { sessionId: this.sessionId, timestamp: new Date().toISOString(), attributes: { + // Extras first: standard fields below win on key collision, so callers + // can never override command.name, error fields, or the fingerprint. + ...(options?.extraAttributes ?? {}), 'command.name': name, 'command.duration_ms': durationMs, 'command.success': success, diff --git a/src/utils/telemetry-types.ts b/src/utils/telemetry-types.ts index 82a067ed..4ea58839 100644 --- a/src/utils/telemetry-types.ts +++ b/src/utils/telemetry-types.ts @@ -91,7 +91,10 @@ export interface CommandEvent extends BaseTelemetryEvent { 'api.resource'?: string; 'cli.version': string; 'workos.user_id'?: string; - } & EnvFingerprint; + // Open for caller-supplied dimensions (e.g. mcp.*) — the gateway schema is + // passthrough and flattens unknown attributes onto the command span. + } & EnvFingerprint & + Record; } export interface CrashEvent extends BaseTelemetryEvent { From ebaf42cdfbf53824c53c4bf0ea94c27197c2f77e Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Mon, 6 Jul 2026 11:21:17 -0500 Subject: [PATCH 4/8] fix: abort the MCP offer prompt at its deadline so it cannot wedge install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 30s Promise.race in maybeOfferMcpInstall returned at the deadline while offerMcpInstall kept running: a never-answered clack.confirm still held stdin (ref'd, raw mode), so the process could not exit and `workos install` stayed wedged despite the wrapper. Thread an AbortController from the deadline into clack.confirm — on abort, clack resolves the prompt as a cancel and releases stdin — and skip install work when an answer lands after the deadline. A pty run with stdin held open now exits at ~30s instead of hanging. Addresses Greptile P1 on #184. --- src/lib/mcp-notice.spec.ts | 60 ++++++++++++++++++++++++++++++++++++++ src/lib/mcp-notice.ts | 37 +++++++++++++++++------ 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/lib/mcp-notice.spec.ts b/src/lib/mcp-notice.spec.ts index a9410755..acb40025 100644 --- a/src/lib/mcp-notice.spec.ts +++ b/src/lib/mcp-notice.spec.ts @@ -60,6 +60,7 @@ const { maybeShowMcpNotice, maybeOfferMcpInstall, resetMcpNoticeState, + MCP_OFFER_TIMEOUT_MS, } = await import('./mcp-notice.js'); const { markStartupNoticeShown, resetStartupNoticeGate } = await import('./startup-notice-gate.js'); @@ -351,6 +352,65 @@ describe('maybeOfferMcpInstall (install-flow prompt)', () => { }); }); + it('aborts a hung prompt at the deadline: stdin released, nothing recorded', async () => { + const CANCEL = Symbol('clack:cancel'); + const cursor = fakeClient('cursor', 'Cursor', { installed: false }); + detectResult = [cursor]; + // A prompt that never gets an answer: it only resolves (as a cancel, the + // way clack does) when the deadline signal aborts it. + confirmMock.mockImplementation( + (opts: { signal?: AbortSignal }) => + new Promise((resolve) => { + opts.signal?.addEventListener('abort', () => resolve(CANCEL), { once: true }); + }), + ); + isCancelMock.mockImplementation((v: unknown) => v === CANCEL); + + vi.useFakeTimers(); + try { + const offer = maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + await vi.advanceTimersByTimeAsync(MCP_OFFER_TIMEOUT_MS); + await expect(offer).resolves.toBeUndefined(); + } finally { + vi.useRealTimers(); + } + + // The prompt must receive the deadline signal — without it, the race + // resolves but the pending confirm keeps stdin (and the process) alive. + expect(confirmMock.mock.calls[0][0].signal).toBeInstanceOf(AbortSignal); + // A timeout is a cancel, not a decline: nothing persisted, nothing emitted. + expect(savePreferencesMock).not.toHaveBeenCalled(); + expect(emitCommandEventMock).not.toHaveBeenCalled(); + expect(cursor.add).not.toHaveBeenCalled(); + }); + + it('does not start installs when the answer lands at the deadline', async () => { + const cursor = fakeClient('cursor', 'Cursor', { installed: false }); + detectResult = [cursor]; + // Simulate a "yes" submitted in the same tick the deadline fires (submit + // beats cancel inside clack): the signal is already aborted by the time + // the flow sees the answer. + confirmMock.mockImplementation( + (opts: { signal?: AbortSignal }) => + new Promise((resolve) => { + opts.signal?.addEventListener('abort', () => resolve(true), { once: true }); + }), + ); + + vi.useFakeTimers(); + try { + const offer = maybeOfferMcpInstall({ entryPoint: 'install-flow' }); + await vi.advanceTimersByTimeAsync(MCP_OFFER_TIMEOUT_MS); + await expect(offer).resolves.toBeUndefined(); + } finally { + vi.useRealTimers(); + } + + // The outer flow already moved on — no detached install work, no emission. + expect(cursor.add).not.toHaveBeenCalled(); + expect(emitCommandEventMock).not.toHaveBeenCalled(); + }); + it('counts already-installed agents as installed in the emission', async () => { const already = fakeClient('codex', 'Codex', { installed: false, diff --git a/src/lib/mcp-notice.ts b/src/lib/mcp-notice.ts index c5fb9e28..e8e37f9b 100644 --- a/src/lib/mcp-notice.ts +++ b/src/lib/mcp-notice.ts @@ -27,8 +27,12 @@ import { hasStartupNoticeShown, markStartupNoticeShown } from './startup-notice- export type McpAskState = { declined: boolean; bannerShown: boolean }; /** - * Best-effort ceiling on the whole install-flow offer so a wedged prompt can - * never hold up `workos install`. Mirrors login.ts's SKILL_INSTALL_TIMEOUT_MS. + * Ceiling on the whole install-flow offer so a wedged prompt can never hold up + * `workos install`. The deadline actively aborts the pending clack prompt (via + * AbortSignal) — clack's cancel path releases stdin and restores raw mode, so + * the process can actually exit; a race alone would leave the prompt's stdin + * handle keeping the event loop alive. Mirrors login.ts's + * SKILL_INSTALL_TIMEOUT_MS. */ export const MCP_OFFER_TIMEOUT_MS = 30 * 1000; @@ -168,7 +172,7 @@ function printInstallMatrix(results: McpClientResult[]): void { * no: record the decline + emit (a decline is an adoption signal). On cancel * (ctrl-C): skip silently without recording — a cancel is not a decline. */ -async function offerMcpInstall(): Promise { +async function offerMcpInstall(signal: AbortSignal): Promise { if (!isPromptAllowed()) return; // the entire mode gate (CI / agent / non-TTY) if (isJsonMode()) return; // never prompt on the machine-readable path (e.g. `install --json` on a TTY) const { declined } = await getMcpAskState(); @@ -178,11 +182,15 @@ async function offerMcpInstall(): Promise { const names = targets.map((t) => t.displayName).join(', '); const offerStartedAt = Date.now(); + // The deadline signal aborts a hung/unanswered prompt: clack resolves it as + // a cancel and releases stdin so the process can exit. const answer = await clack.confirm({ message: `Add the WorkOS MCP server to ${names}? Your coding agent gets tools to manage WorkOS resources (you'll authorize via OAuth on first use).`, + signal, }); - // Cancel (ctrl-C) is not a decline — skip silently, ask again next time. + // Cancel (ctrl-C or deadline abort) is not a decline — skip silently, ask + // again next time. if (clack.isCancel(answer)) return; // Adoption events are queued command events, NOT capture(): the installer @@ -205,6 +213,10 @@ async function offerMcpInstall(): Promise { return; } + // The user submitted right as the deadline fired: the outer flow has already + // moved on, so don't start install work it will never report on. + if (signal.aborted) return; + const results: McpClientResult[] = []; for (const target of targets) { results.push(await target.add()); @@ -230,20 +242,27 @@ async function offerMcpInstall(): Promise { /** * Offer to install the WorkOS MCP server at the end of `workos install`. * - * Wraps offerMcpInstall best-effort: a try/catch AND a 30s unref'd-timeout race - * (login.ts pattern) so the offer can never throw into, wedge, or fail the - * install flow. `workos install` has already succeeded by the time this runs. + * Wraps offerMcpInstall best-effort: a try/catch AND a 30s deadline so the + * offer can never throw into, wedge, or fail the install flow. The deadline + * aborts the pending prompt (AbortSignal → clack cancel, which releases stdin); + * the race is a backstop in case the flow is wedged somewhere that can't be + * aborted (client shell-outs are separately bounded by their exec timeouts). + * `workos install` has already succeeded by the time this runs. */ export async function maybeOfferMcpInstall(_opts: { entryPoint: 'install-flow' }): Promise { let timeoutHandle: ReturnType | undefined; + const deadline = new AbortController(); try { const timeout = new Promise((resolve) => { - timeoutHandle = setTimeout(() => resolve(), MCP_OFFER_TIMEOUT_MS); + timeoutHandle = setTimeout(() => { + deadline.abort(); + resolve(); + }, MCP_OFFER_TIMEOUT_MS); // Don't keep the event loop alive on this timer — the process should exit // as soon as everything else settles. timeoutHandle.unref?.(); }); - await Promise.race([offerMcpInstall(), timeout]); + await Promise.race([offerMcpInstall(deadline.signal), timeout]); } catch { // The MCP offer must never fail or block `workos install`. } finally { From 49367fea8e4e0e0565af0ce29a8bb3c9e899741e Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Mon, 6 Jul 2026 11:51:09 -0500 Subject: [PATCH 5/8] chore: update pnpm-lock --- pnpm-lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 683c4b49..0fa41572 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2226,7 +2226,7 @@ packages: optional: true tree-sitter-kotlin@https://codeload.github.com/fwcd/tree-sitter-kotlin/tar.gz/f66d2908542e93c0204c6c241f794afe4e9cd5d1: - resolution: {gitHosted: true, integrity: sha512-7pk1Tg/gXh+6hM4E0F2rPKeLyA/bNlYyqVu6T1Md/AV/vloakbvEZG0R4CYwUfVtgFAMZRbOtA8JBzX1SFatBA==, tarball: https://codeload.github.com/fwcd/tree-sitter-kotlin/tar.gz/f66d2908542e93c0204c6c241f794afe4e9cd5d1} + resolution: {gitHosted: true, tarball: https://codeload.github.com/fwcd/tree-sitter-kotlin/tar.gz/f66d2908542e93c0204c6c241f794afe4e9cd5d1} version: 0.4.0 peerDependencies: tree-sitter: ^0.21.1 From 159d22cd26e1d8c99fe39fc1b629218082adecc1 Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Mon, 6 Jul 2026 11:57:43 -0500 Subject: [PATCH 6/8] chore: restore pnpm-lock to the branch's pinned resolution Commit 9464704 was regenerated without a lockfile by pnpm 8 (a stale mise shim shadowing the repo's pnpm@10.28.2): it downgraded the lockfile to v6 format and bumped in-range transitive deps, including @anthropic-ai/claude-agent-sdk 0.2.62 -> 0.2.141, whose SDKResultError type change broke the build. This restores the v9 lockfile as of 4136f62; `pnpm i --frozen-lockfile`, build, and the full test suite pass again. --- pnpm-lock.yaml | 528 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 502 insertions(+), 26 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0fa41572..bd377807 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -125,7 +125,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.0.18 - version: 4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) packages: @@ -283,6 +283,15 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} + '@bundled-es-modules/cookie@2.0.1': + resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==} + + '@bundled-es-modules/statuses@1.0.1': + resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} + + '@bundled-es-modules/tough-cookie@0.1.6': + resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==} + '@clack/core@1.4.2': resolution: {integrity: sha512-0Ty/1Gfm+Kb07sXcuESjyKfwEhSy4Ns1AgeEisHb/bDY5fWme0tTeTkU14T1Gmcs17YIjB/teiDe4uaCghbYqQ==} engines: {node: '>= 20.12.0'} @@ -466,6 +475,41 @@ packages: peerDependencies: hono: ^4 + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -486,6 +530,10 @@ packages: '@cfworker/json-schema': optional: true + '@mswjs/interceptors@0.39.8': + resolution: {integrity: sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA==} + engines: {node: '>=18'} + '@napi-rs/keyring-darwin-arm64@1.3.0': resolution: {integrity: sha512-pl76hJvdYUBn6I24bXiOBMA9nbDapo3I5B+f3OorjDU4dUMSypXeKbOVehJe8fhgTiH24flMyTS3aAIy43xegQ==} engines: {node: '>= 10'} @@ -588,6 +636,19 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + + '@open-draft/logger@0.3.0': + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + + '@open-draft/until@2.1.0': + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + '@oxc-project/types@0.138.0': resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} @@ -990,6 +1051,9 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -1012,6 +1076,12 @@ packages: '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@types/statuses@2.0.6': + resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} + + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -1116,6 +1186,14 @@ packages: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} @@ -1193,10 +1271,18 @@ packages: resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} engines: {node: '>=4'} - cli-truncate@5.2.0: - resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} + cli-truncate@5.1.1: + resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} engines: {node: '>=20'} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + cliui@9.0.1: resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} engines: {node: '>=20'} @@ -1205,6 +1291,13 @@ packages: resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} @@ -1344,8 +1437,8 @@ packages: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} - es-toolkit@1.49.0: - resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} + es-toolkit@1.44.0: + resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} @@ -1496,6 +1589,14 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-east-asian-width@1.6.0: resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} @@ -1540,6 +1641,9 @@ packages: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} + headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + hono@4.12.28: resolution: {integrity: sha512-YwUvVpSF7m1yOblFPrU3Hbo8XhPheBoiyfGuII6z19LnOr6JpDnyyp7LFNrfV56wS8tpvtBFGRISHN02pDdLOA==} engines: {node: '>=16.9.0'} @@ -1600,6 +1704,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + is-fullwidth-code-point@5.1.0: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} @@ -1622,6 +1730,9 @@ packages: engines: {node: '>=14.16'} hasBin: true + is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -1831,6 +1942,20 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + msw@2.10.4: + resolution: {integrity: sha512-6R1or/qyele7q3RyPwNuvc0IxO8L8/Aim6Sz5ncXEgcWUNxSKE+udriTOWHtpMwmfkLYlacA2y7TIx4cL5lgHA==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + nanoid@3.3.15: resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1868,6 +1993,9 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + obug@2.1.3: resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} engines: {node: '>=12.20.0'} @@ -1892,6 +2020,9 @@ packages: engines: {node: '>=8'} deprecated: The package has been renamed to `open` + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + oxfmt@0.56.0: resolution: {integrity: sha512-9Dv0wV3zKiyvhjD7bRKaInKmHQ1sPx3RGOjQkGFJbbdQ16576yf8qhMSO9Q9cvHcs+1NpBsRTkuDDYFFPTJ6gw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1941,6 +2072,9 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + path-to-regexp@8.4.2: resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} @@ -1954,6 +2088,10 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + picomatch@4.0.5: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} @@ -1982,10 +2120,20 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + qs@6.15.3: resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} engines: {node: '>=0.6'} + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2007,10 +2155,17 @@ packages: resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} engines: {node: '>=0.10.0'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + restore-cursor@4.0.0: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2094,6 +2249,10 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -2101,6 +2260,10 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + slice-ansi@8.0.0: resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} engines: {node: '>=20'} @@ -2126,6 +2289,9 @@ packages: std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2134,6 +2300,10 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.2.0: + resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + engines: {node: '>=20'} + string-width@8.2.1: resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} @@ -2196,6 +2366,10 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + tree-sitter-c-sharp@0.23.1: resolution: {integrity: sha512-9zZ4FlcTRWWfRf6f4PgGhG8saPls6qOOt75tDfX7un9vQZJmARjPrAC6yBNCX2T/VKcCjIDbgq0evFaB3iGhQw==} peerDependencies: @@ -2295,8 +2469,12 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - type-fest@5.8.0: - resolution: {integrity: sha512-YGYEVz3Fm5iy/AybuA0oyNFq7H4CgQNfRp/qfe8nurE1kuCeNm3/vfm9X4Mtl+qLyaKJUh5xrFZwogr41SMjYA==} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + type-fest@5.4.4: + resolution: {integrity: sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==} engines: {node: '>=20'} type-is@2.1.0: @@ -2316,10 +2494,17 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + uuid@13.0.2: resolution: {integrity: sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==} hasBin: true @@ -2430,6 +2615,18 @@ packages: resolution: {integrity: sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA==} engines: {node: '>=20'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -2437,6 +2634,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.21.0: resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} @@ -2472,10 +2681,18 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + yargs-parser@22.0.0: resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + yargs@18.0.0: resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} @@ -2484,6 +2701,10 @@ packages: resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} engines: {node: '>=12.20'} + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + yoga-layout@3.2.1: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} @@ -2710,6 +2931,22 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} + '@bundled-es-modules/cookie@2.0.1': + dependencies: + cookie: 0.7.2 + optional: true + + '@bundled-es-modules/statuses@1.0.1': + dependencies: + statuses: 2.0.2 + optional: true + + '@bundled-es-modules/tough-cookie@0.1.6': + dependencies: + '@types/tough-cookie': 4.0.5 + tough-cookie: 4.1.4 + optional: true + '@clack/core@1.4.2': dependencies: fast-wrap-ansi: 0.2.2 @@ -2825,6 +3062,39 @@ snapshots: dependencies: hono: 4.12.28 + '@inquirer/ansi@1.0.2': + optional: true + + '@inquirer/confirm@5.1.21(@types/node@22.20.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@22.20.0) + '@inquirer/type': 3.0.10(@types/node@22.20.0) + optionalDependencies: + '@types/node': 22.20.0 + optional: true + + '@inquirer/core@10.3.2(@types/node@22.20.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.20.0) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 22.20.0 + optional: true + + '@inquirer/figures@1.0.15': + optional: true + + '@inquirer/type@3.0.10(@types/node@22.20.0)': + optionalDependencies: + '@types/node': 22.20.0 + optional: true + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -2856,6 +3126,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@mswjs/interceptors@0.39.8': + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.3 + strict-event-emitter: 0.5.1 + optional: true + '@napi-rs/keyring-darwin-arm64@1.3.0': optional: true @@ -2928,6 +3208,21 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@open-draft/deferred-promise@2.2.0': + optional: true + + '@open-draft/logger@0.3.0': + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.3 + optional: true + + '@open-draft/until@2.1.0': + optional: true + + '@opentelemetry/api@1.9.0': + optional: true + '@oxc-project/types@0.138.0': {} '@oxfmt/binding-android-arm-eabi@0.56.0': @@ -3189,6 +3484,9 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/cookie@0.6.0': + optional: true + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.9': {} @@ -3209,6 +3507,12 @@ snapshots: '@types/semver@7.7.1': {} + '@types/statuses@2.0.6': + optional: true + + '@types/tough-cookie@4.0.5': + optional: true + '@types/yargs-parser@21.0.3': {} '@types/yargs@17.0.35': @@ -3227,7 +3531,7 @@ snapshots: obug: 2.1.3 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) '@vitest/expect@4.1.10': dependencies: @@ -3238,12 +3542,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.10(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: + msw: 2.10.4(@types/node@22.20.0)(typescript@5.9.3) vite: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': @@ -3273,7 +3578,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vitest: 4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) '@vitest/utils@4.1.10': dependencies: @@ -3363,6 +3668,13 @@ snapshots: ansi-regex@6.2.2: {} + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + optional: true + + ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} anynum@1.0.1: {} @@ -3435,11 +3747,21 @@ snapshots: dependencies: string-width: 4.2.3 - cli-truncate@5.2.0: + cli-truncate@5.1.1: dependencies: - slice-ansi: 8.0.0 + slice-ansi: 7.1.2 string-width: 8.2.1 + cli-width@4.1.0: + optional: true + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + optional: true + cliui@9.0.1: dependencies: string-width: 7.2.0 @@ -3450,6 +3772,14 @@ snapshots: dependencies: convert-to-spaces: 2.0.1 + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + optional: true + + color-name@1.1.4: + optional: true + colorette@1.4.0: {} commander@13.1.0: {} @@ -3544,7 +3874,7 @@ snapshots: dependencies: es-errors: 1.3.0 - es-toolkit@1.49.0: {} + es-toolkit@1.44.0: {} esbuild@0.28.1: optionalDependencies: @@ -3742,6 +4072,10 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.3.0: {} + + get-east-asian-width@1.5.0: {} + get-east-asian-width@1.6.0: {} get-intrinsic@1.3.0: @@ -3791,6 +4125,9 @@ snapshots: dependencies: function-bind: 1.1.2 + headers-polyfill@4.0.3: + optional: true + hono@4.12.28: {} html-escaper@2.0.2: {} @@ -3822,14 +4159,14 @@ snapshots: dependencies: '@alcalzone/ansi-tokenize': 0.2.5 ansi-escapes: 7.3.0 - ansi-styles: 6.2.3 + ansi-styles: 6.2.1 auto-bind: 5.0.1 chalk: 5.6.2 cli-boxes: 3.0.0 cli-cursor: 4.0.0 - cli-truncate: 5.2.0 + cli-truncate: 5.1.1 code-excerpt: 4.0.0 - es-toolkit: 1.49.0 + es-toolkit: 1.44.0 indent-string: 5.0.0 is-in-ci: 2.0.0 patch-console: 2.0.0 @@ -3839,12 +4176,12 @@ snapshots: signal-exit: 3.0.7 slice-ansi: 8.0.0 stack-utils: 2.0.6 - string-width: 8.2.1 + string-width: 8.2.0 terminal-size: 4.0.1 - type-fest: 5.8.0 + type-fest: 5.4.4 widest-line: 6.0.0 - wrap-ansi: 9.0.2 - ws: 8.21.0 + wrap-ansi: 9.0.0 + ws: 8.19.0 yoga-layout: 3.2.1 optionalDependencies: '@types/react': 19.2.17 @@ -3862,6 +4199,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + is-fullwidth-code-point@5.1.0: dependencies: get-east-asian-width: 1.6.0 @@ -3878,6 +4219,9 @@ snapshots: dependencies: is-docker: 3.0.0 + is-node-process@1.2.0: + optional: true + is-number@7.0.0: {} is-promise@4.0.0: {} @@ -4043,6 +4387,35 @@ snapshots: ms@2.1.3: {} + msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3): + dependencies: + '@bundled-es-modules/cookie': 2.0.1 + '@bundled-es-modules/statuses': 1.0.1 + '@bundled-es-modules/tough-cookie': 0.1.6 + '@inquirer/confirm': 5.1.21(@types/node@22.20.0) + '@mswjs/interceptors': 0.39.8 + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.6.0 + '@types/statuses': 2.0.6 + graphql: 16.14.2 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + strict-event-emitter: 0.5.1 + type-fest: 4.41.0 + yargs: 17.7.3 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + optional: true + + mute-stream@2.0.0: + optional: true + nanoid@3.3.15: {} negotiator@1.0.0: {} @@ -4065,6 +4438,8 @@ snapshots: object-inspect@1.13.4: {} + obug@2.1.1: {} + obug@2.1.3: {} on-finished@2.4.1: @@ -4092,6 +4467,9 @@ snapshots: dependencies: is-wsl: 1.1.0 + outvariant@1.4.3: + optional: true + oxfmt@0.56.0: dependencies: tinypool: 2.1.0 @@ -4154,6 +4532,9 @@ snapshots: path-key@3.1.1: {} + path-to-regexp@6.3.0: + optional: true + path-to-regexp@8.4.2: {} pathe@2.0.3: {} @@ -4162,6 +4543,8 @@ snapshots: picomatch@2.3.2: {} + picomatch@4.0.4: {} + picomatch@4.0.5: {} pkce-challenge@5.0.1: {} @@ -4186,11 +4569,22 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + psl@1.15.0: + dependencies: + punycode: 2.3.1 + optional: true + + punycode@2.3.1: + optional: true + qs@6.15.3: dependencies: es-define-property: 1.0.1 side-channel: 1.1.1 + querystringify@2.2.0: + optional: true + queue-microtask@1.2.3: {} range-parser@1.3.0: {} @@ -4209,8 +4603,14 @@ snapshots: react@19.2.7: {} + require-directory@2.1.1: + optional: true + require-from-string@2.0.2: {} + requires-port@1.0.0: + optional: true + restore-cursor@4.0.0: dependencies: onetime: 5.1.2 @@ -4330,6 +4730,9 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: + optional: true + sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -4338,6 +4741,11 @@ snapshots: sisteransi@1.0.5: {} + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.0.0 + slice-ansi@8.0.0: dependencies: ansi-styles: 6.2.3 @@ -4360,6 +4768,9 @@ snapshots: std-env@4.1.0: {} + strict-event-emitter@0.5.1: + optional: true + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -4372,9 +4783,14 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 + string-width@8.2.0: + dependencies: + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + string-width@8.2.1: dependencies: - get-east-asian-width: 1.6.0 + get-east-asian-width: 1.5.0 strip-ansi: 7.2.0 strip-ansi@6.0.1: @@ -4422,6 +4838,14 @@ snapshots: totalist@3.0.1: {} + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + optional: true + tree-sitter-c-sharp@0.23.1(tree-sitter@0.21.1): dependencies: node-addon-api: 8.9.0 @@ -4505,7 +4929,10 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - type-fest@5.8.0: + type-fest@4.41.0: + optional: true + + type-fest@5.4.4: dependencies: tagged-tag: 1.0.0 @@ -4521,8 +4948,17 @@ snapshots: undici-types@6.21.0: {} + universalify@0.2.0: + optional: true + unpipe@1.0.0: {} + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + optional: true + uuid@13.0.2: {} vary@1.1.2: {} @@ -4541,10 +4977,10 @@ snapshots: tsx: 4.23.0 yaml: 2.9.0 - vitest@4.1.10(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)): + vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.20.0)(@vitest/coverage-v8@4.1.10)(@vitest/ui@4.1.10)(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(msw@2.10.4(@types/node@22.20.0)(typescript@5.9.3))(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -4553,9 +4989,9 @@ snapshots: es-module-lexer: 2.3.0 expect-type: 1.4.0 magic-string: 0.30.21 - obug: 2.1.3 + obug: 2.1.1 pathe: 2.0.3 - picomatch: 4.0.5 + picomatch: 4.0.4 std-env: 4.1.0 tinybench: 2.9.0 tinyexec: 1.2.4 @@ -4564,6 +5000,7 @@ snapshots: vite: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: + '@opentelemetry/api': 1.9.0 '@types/node': 22.20.0 '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) '@vitest/ui': 4.1.10(vitest@4.1.10) @@ -4585,6 +5022,26 @@ snapshots: dependencies: string-width: 8.2.1 + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + optional: true + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + optional: true + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -4593,6 +5050,8 @@ snapshots: wrappy@1.0.2: {} + ws@8.19.0: {} + ws@8.21.0: {} wsl-utils@0.3.1: @@ -4610,8 +5069,22 @@ snapshots: yaml@2.9.0: {} + yargs-parser@21.1.1: + optional: true + yargs-parser@22.0.0: {} + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + optional: true + yargs@18.0.0: dependencies: cliui: 9.0.1 @@ -4623,6 +5096,9 @@ snapshots: yocto-queue@1.2.2: {} + yoctocolors-cjs@2.1.3: + optional: true + yoga-layout@3.2.1: {} zod-to-json-schema@3.25.2(zod@4.4.3): From 400320b5cb6d9aba795341440411442048b54baf Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Mon, 6 Jul 2026 12:31:23 -0500 Subject: [PATCH 7/8] chore: formatting --- src/commands/mcp.spec.ts | 9 +++++++-- src/lib/mcp-clients.ts | 8 +------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/commands/mcp.spec.ts b/src/commands/mcp.spec.ts index cd7d2332..d3abf6b1 100644 --- a/src/commands/mcp.spec.ts +++ b/src/commands/mcp.spec.ts @@ -169,7 +169,10 @@ describe('Claude Code client', () => { }); it('isInstalled matches the workos: list line', async () => { - mockExec(() => ({ status: 0, stdout: 'raindrop: https://x (HTTP)\nworkos: https://mcp.workos.com/mcp (HTTP) - Connected' })); + mockExec(() => ({ + status: 0, + stdout: 'raindrop: https://x (HTTP)\nworkos: https://mcp.workos.com/mcp (HTTP) - Connected', + })); expect(await claude().isInstalled()).toBe(true); }); @@ -397,7 +400,9 @@ describe('JSON output mode', () => { it('runMcpInstall still emits the full matrix before exiting 1 on failure', async () => { makeDir('.claude'); makeDir('.cursor'); - mockExec((_c, args) => (args.includes('add') && args.includes('--transport') ? { status: 1, stderr: 'bad' } : { status: 0 })); + mockExec((_c, args) => + args.includes('add') && args.includes('--transport') ? { status: 1, stderr: 'bad' } : { status: 0 }, + ); const exit = await captureExit(() => runMcpInstall()); expect(exit?.exitCode).toBe(1); const output = JSON.parse(consoleOutput[0]); diff --git a/src/lib/mcp-clients.ts b/src/lib/mcp-clients.ts index fb764f2c..ab6935df 100644 --- a/src/lib/mcp-clients.ts +++ b/src/lib/mcp-clients.ts @@ -38,13 +38,7 @@ const JSONC_MODIFY_OPTIONS: jsonc.ModificationOptions = { export type McpAgentKey = 'claude-code' | 'codex' | 'cursor'; -export type McpOutcome = - | 'installed' - | 'already-installed' - | 'removed' - | 'not-installed' - | 'skipped' - | 'failed'; +export type McpOutcome = 'installed' | 'already-installed' | 'removed' | 'not-installed' | 'skipped' | 'failed'; export interface McpClientResult { agent: McpAgentKey; From f0ad593f73af3cce999c81416275ef4c530fae96 Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Mon, 6 Jul 2026 12:33:01 -0500 Subject: [PATCH 8/8] chore: fix linting --- src/emulate/workos/index.ts | 2 +- src/utils/analytics.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/emulate/workos/index.ts b/src/emulate/workos/index.ts index a5541c3c..83befa72 100644 --- a/src/emulate/workos/index.ts +++ b/src/emulate/workos/index.ts @@ -1,7 +1,7 @@ import { randomBytes } from 'node:crypto'; import type { ServicePlugin, Store, RouteContext } from '../core/index.js'; import { generateId } from '../core/index.js'; -import { getWorkOSStore, type WorkOSStore } from './store.js'; +import { getWorkOSStore } from './store.js'; import { organizationRoutes } from './routes/organizations.js'; import { organizationDomainRoutes } from './routes/organization-domains.js'; import { membershipRoutes } from './routes/memberships.js'; diff --git a/src/utils/analytics.ts b/src/utils/analytics.ts index 7ffc71b3..070ee3a0 100644 --- a/src/utils/analytics.ts +++ b/src/utils/analytics.ts @@ -309,7 +309,7 @@ export class Analytics { attributes: { // Extras first: standard fields below win on key collision, so callers // can never override command.name, error fields, or the fingerprint. - ...(options?.extraAttributes ?? {}), + ...options?.extraAttributes, 'command.name': name, 'command.duration_ms': durationMs, 'command.success': success,