diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6bd8d32..f02daff3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,12 @@ jobs: - run: npm run build:all + - name: Verify generated schemas are up-to-date + run: | + npm run generate:schemas + npm run prettier:fix + git diff --exit-code src/generated/ || (echo "Generated schemas are out of date. Run 'npm run generate:schemas' and commit." && exit 1) + - run: npm test - run: npm run prettier diff --git a/.husky/pre-commit b/.husky/pre-commit index cffd5624..6cc0dca3 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1,5 @@ npm run build:all npm run prettier:fix + +# Stage any changes to generated files (they may have been reformatted by prettier) +git add src/generated/ diff --git a/package-lock.json b/package-lock.json index 53c702a3..0ac7d011 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,8 @@ "husky": "^9.1.7", "nodemon": "^3.1.0", "prettier": "^3.6.2", + "ts-to-zod": "^5.1.0", + "tsx": "^4.21.0", "typedoc": "^0.28.14", "typescript": "^5.9.3" }, @@ -599,6 +601,29 @@ "node": ">=6.9.0" } }, + "node_modules/@clack/core": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.0.0-alpha.4.tgz", + "integrity": "sha512-VCtU+vjyKPMSakVrB9q1bOnXN7QW/w4+YQDQCOF59GrzydW+169i0fVx/qzRRXJgt8KGj/pZZ/JxXroFZIDByg==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.0.0-alpha.4.tgz", + "integrity": "sha512-KnmtDF2xQGoI5AlBme9akHtvCRV0RKAARUXHBQO2tMwnY8B08/4zPWigT7uLK25UPrMCEqnyQPkKRjNdhPbf8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@clack/core": "1.0.0-alpha.4", + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, "node_modules/@dimforge/rapier3d-compat": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", @@ -1129,6 +1154,75 @@ } } }, + "node_modules/@oclif/core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.8.0.tgz", + "integrity": "sha512-jteNUQKgJHLHFbbz806aGZqf+RJJ7t4gwF4MYa8fCwCxQ8/klJNWc0MvaJiBebk7Mc+J39mdlsB4XraaCKznFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "ansis": "^3.17.0", + "clean-stack": "^3.0.1", + "cli-spinners": "^2.9.2", + "debug": "^4.4.3", + "ejs": "^3.1.10", + "get-package-type": "^0.1.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "lilconfig": "^3.1.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "string-width": "^4.2.3", + "supports-color": "^8", + "tinyglobby": "^0.2.14", + "widest-line": "^3.1.0", + "wordwrap": "^1.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/core/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@oclif/core/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@oclif/core/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@oven/bun-darwin-aarch64": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.3.4.tgz", @@ -1848,6 +1942,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript/vfs": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.2.tgz", + "integrity": "sha512-hoBwJwcbKHmvd2QVebiytN1aELvpk9B74B4L1mFm/XT1Q/VOYAWl2vQ9AWRFtQq8zmz6enTpfTV8WRc4ATjW/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + }, + "peerDependencies": { + "typescript": "*" + } + }, "node_modules/@vitejs/plugin-react": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", @@ -2026,6 +2133,22 @@ } } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2050,6 +2173,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2078,6 +2211,13 @@ "node": ">=12" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2389,6 +2529,114 @@ "fsevents": "~2.3.2" } }, + "node_modules/clean-stack": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", + "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", + "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2425,6 +2673,13 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2583,6 +2838,22 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.266", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", @@ -2615,6 +2886,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -2703,6 +2987,19 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -2720,6 +3017,13 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, "node_modules/eventsource": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", @@ -2831,6 +3135,39 @@ "dev": true, "license": "MIT" }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -2919,6 +3256,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -2942,6 +3292,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -2954,6 +3314,19 @@ "node": ">= 0.4" } }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -3063,6 +3436,16 @@ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "dev": true }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -3088,6 +3471,22 @@ "node": ">=8" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3132,11 +3531,42 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" }, - "node_modules/isexe": { + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jose": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", @@ -3180,6 +3610,19 @@ "node": ">=6" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", @@ -3189,6 +3632,230 @@ "uc.micro": "^2.0.0" } }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/loupe": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", @@ -3312,6 +3979,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3469,6 +4149,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3698,6 +4394,40 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rollup": { "version": "4.53.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", @@ -3931,6 +4661,19 @@ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -3955,27 +4698,93 @@ "node": ">=10" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true + "node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "engines": { + "node": ">= 0.8" } }, "node_modules/std-env": { @@ -4033,183 +4842,998 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/system-monitor-server": { + "resolved": "examples/system-monitor-server", + "link": true + }, + "node_modules/systeminformation": { + "version": "5.27.11", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.11.tgz", + "integrity": "sha512-K3Lto/2m3K2twmKHdgx5B+0in9qhXK4YnoT9rIlgwN/4v7OV5c8IjbeAUkuky/6VzCQC7iKCAqi8rZathCdjHg==", + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, + "node_modules/text-camel-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-camel-case/-/text-camel-case-1.2.9.tgz", + "integrity": "sha512-wKYs9SgRxYizJE1mneR7BbLNlGw2IYzJAS8XwkWIry0CTbO1gvvPkFsx5Z1/hr+VqUaBqx9q3yKd30HpZLdMsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-pascal-case": "1.2.9" + } + }, + "node_modules/text-capital-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-capital-case/-/text-capital-case-1.2.9.tgz", + "integrity": "sha512-X5zV8U8pxtq2xS2t46lgAWqZdDbgWMKq03MQSNwY2CJdQCsdTNh144E2Q/q9wBxWzSBUXn+jRc9kF+Gs8/pGhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-case/-/text-case-1.2.9.tgz", + "integrity": "sha512-zZVdA8rMcjx9zhekdUuOPZShc25UTV7W8/ddKbgbPtfCEvIiToPtWiSd2lXLSuiGMovNhJ4+Tw49xll9o9ts+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-camel-case": "1.2.9", + "text-capital-case": "1.2.9", + "text-constant-case": "1.2.9", + "text-dot-case": "1.2.9", + "text-header-case": "1.2.9", + "text-is-lower-case": "1.2.9", + "text-is-upper-case": "1.2.9", + "text-kebab-case": "1.2.9", + "text-lower-case": "1.2.9", + "text-lower-case-first": "1.2.9", + "text-no-case": "1.2.9", + "text-param-case": "1.2.9", + "text-pascal-case": "1.2.9", + "text-path-case": "1.2.9", + "text-sentence-case": "1.2.9", + "text-snake-case": "1.2.9", + "text-swap-case": "1.2.9", + "text-title-case": "1.2.9", + "text-upper-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-constant-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-constant-case/-/text-constant-case-1.2.9.tgz", + "integrity": "sha512-Vosm6nC7Gag+JFakJHwqS9AXRNgl07j5KZ7srU9cYuKRzYwrxzeJ4RpEogRBNHw7CfmOm0j5FGEznblWtu7pIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case": "1.2.9" + } + }, + "node_modules/text-dot-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-dot-case/-/text-dot-case-1.2.9.tgz", + "integrity": "sha512-N83hsnvGdSO9q9AfNSB9Cy1LFDNN2MCx53LcxtaPoDWPUTk47fv0JlvIY1tgY0wyzCiThF03kVj3jworvAOScA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9" + } + }, + "node_modules/text-header-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-header-case/-/text-header-case-1.2.9.tgz", + "integrity": "sha512-TqryEKcYisQAfWLbtT3xPnZlMZ/mySO1uS+LUg+B0eNuqgETrSzVpXIUj5E6Zf/EyJHgpZf4VndbAXtOMJuT4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-capital-case": "1.2.9" + } + }, + "node_modules/text-is-lower-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-is-lower-case/-/text-is-lower-case-1.2.9.tgz", + "integrity": "sha512-cEurrWSnYVYqL8FSwl5cK4mdfqF7qNDCcKJgXI3NnfTesiB8umxAhdlQoErrRYI1xEvYr2WN0MI333EehUhQjg==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-is-upper-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-is-upper-case/-/text-is-upper-case-1.2.9.tgz", + "integrity": "sha512-HxsWr3VCsXXiLlhD0c+Ey+mS2lOTCiSJbkepjaXNHl2bp33KiscQaiG0qLwQmmpZQm4SJCg2s9FkndxS0RNDLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-kebab-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-kebab-case/-/text-kebab-case-1.2.9.tgz", + "integrity": "sha512-nOUyNR5Ej2B9D/wyyXfwUEv26+pQuOb1pEX+ojE37mCIWo8QeOxw5y6nxuqDmG7NrEPzbO6265UMV+EICH13Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9" + } + }, + "node_modules/text-lower-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-lower-case/-/text-lower-case-1.2.9.tgz", + "integrity": "sha512-53AOnDrhPpiAUQkgY1SHleKUXp/u7GsqRX13NcCREZscmtjLLJ099uxMRjkK7q2KwHkFYVPl9ytkQlTkTQLS0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-lower-case-first": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-lower-case-first/-/text-lower-case-first-1.2.9.tgz", + "integrity": "sha512-iiphHTV7PVH0MljrEQUA9iBE7jfDpXoi4RQju3WzZU3BRVbS6540cNZgxR19hWa0z6z/7cJTH0Ls9LPBaiUfKg==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-no-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-no-case/-/text-no-case-1.2.9.tgz", + "integrity": "sha512-IcCt328KaapimSrytP4ThfC8URmHZb2DgOqCL9BYvGjpxY2lDiqCkIQk9sClZtwcELs2gTnq83a7jNc573FTLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-lower-case": "1.2.9" + } + }, + "node_modules/text-param-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-param-case/-/text-param-case-1.2.9.tgz", + "integrity": "sha512-nR/Ju9amY3aQS1en2CUCgqN/ZiZIVdDyjlJ3xX5J92ChBevGuA4o9K10fh3JGMkbzK97Vcb+bWQJ4Q+Svz+GyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.9" + } + }, + "node_modules/text-pascal-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-pascal-case/-/text-pascal-case-1.2.9.tgz", + "integrity": "sha512-o6ZxMGjWDTUW54pcghpXes+C2PqbYRMdU5mHrIhueb6z6nq1NueiIOeCUdrSjN/3wXfhCmnFjK7/d9aRGZNqSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9" + } + }, + "node_modules/text-path-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-path-case/-/text-path-case-1.2.9.tgz", + "integrity": "sha512-s8cJ6r5TkJp5ticXMgtxd7f12odEN4d1CfX5u4aoz6jcUtBR2lDqzIhVimkqWFMJ4UKPSrmilUha8Xc2BPi+ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.9" + } + }, + "node_modules/text-sentence-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-sentence-case/-/text-sentence-case-1.2.9.tgz", + "integrity": "sha512-/G/Yi5kZfUa1edFRV4O3lGZAkbDZTFvlwW8CYfH7szkEGe2k2MYEYbOyAkGRVQEGV6V6JiuUAaP3VS9c1tB6nQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-snake-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-snake-case/-/text-snake-case-1.2.9.tgz", + "integrity": "sha512-+ZrqK19ynF/TLQZ7ynqVrL2Dy04uu9syYZwsm8PhzUdsY3XrwPy6QiRqhIEFqhyWbShPcfyfmheer5UEQqFxlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.9" + } + }, + "node_modules/text-swap-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-swap-case/-/text-swap-case-1.2.9.tgz", + "integrity": "sha512-g5fp12ldktYKK9wdHRMvvtSCQrZYNv/D+ZGLumDsvAY4q9T5bCMO2IWMkIP1F5gVQrysdHH6Xv877P/pjUq1iw==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-title-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-title-case/-/text-title-case-1.2.9.tgz", + "integrity": "sha512-RAtC9cdmPp41ns5/HXZBsaQg71BsHT7uZpj2ojTtuFa8o2dNuRYYOrSmy5YdLRIAJQ6WK5hQVpV3jHuq7a+4Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-upper-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-upper-case/-/text-upper-case-1.2.9.tgz", + "integrity": "sha512-K/0DNT7a4z8eah2spARtoJllTZyrNTo6Uc0ujhN/96Ir9uJ/slpahfs13y46H9osL3daaLl3O7iXOkW4xtX6bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-upper-case-first": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-upper-case-first/-/text-upper-case-first-1.2.9.tgz", + "integrity": "sha512-wEDD1B6XqJmEV+xEnBJd+2sBCHZ+7fvA/8Rv/o8+dAsp05YWjYP/kjB8sPH6zqzW0s6jtehIg4IlcKjcYxk2CQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/three": { + "version": "0.181.2", + "resolved": "https://registry.npmjs.org/three/-/three-0.181.2.tgz", + "integrity": "sha512-k/CjiZ80bYss6Qs7/ex1TBlPD11whT9oKfT8oTGiHa34W4JRd1NiH/Tr1DbHWQ2/vMUypxksLnF2CfmlmM5XFQ==", + "license": "MIT" + }, + "node_modules/threejs-server": { + "resolved": "examples/threejs-server", + "link": true + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-to-zod": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ts-to-zod/-/ts-to-zod-5.1.0.tgz", + "integrity": "sha512-giqqlvRHunlJqG9tBL/KAO3wWIVZGF//mZiWLKm/fdQnKnz4EN2mtiK5cugN9slytBkdMEXQIaLvMzIScbhhFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@clack/prompts": "1.0.0-alpha.4", + "@oclif/core": "^4.5.4", + "@typescript/vfs": "^1.5.0", + "chokidar": "^4.0.3", + "listr2": "^9.0.4", + "slash": "^5.1.0", + "text-case": "^1.2.4", + "tslib": "^2.3.1", + "tsutils": "^3.21.0", + "typescript": "^5.2.2", + "zod": "^4.1.5" + }, + "bin": { + "ts-to-zod": "bin/run" + } + }, + "node_modules/ts-to-zod/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ts-to-zod/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ts-to-zod/node_modules/zod": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", + "integrity": "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.1.tgz", + "integrity": "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz", + "integrity": "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.1.tgz", + "integrity": "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", + "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz", + "integrity": "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz", + "integrity": "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz", + "integrity": "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz", + "integrity": "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz", + "integrity": "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz", + "integrity": "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz", + "integrity": "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz", + "integrity": "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz", + "integrity": "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz", + "integrity": "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz", + "integrity": "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=18" } }, - "node_modules/system-monitor-server": { - "resolved": "examples/system-monitor-server", - "link": true - }, - "node_modules/systeminformation": { - "version": "5.27.11", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.11.tgz", - "integrity": "sha512-K3Lto/2m3K2twmKHdgx5B+0in9qhXK4YnoT9rIlgwN/4v7OV5c8IjbeAUkuky/6VzCQC7iKCAqi8rZathCdjHg==", + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz", + "integrity": "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, "os": [ - "darwin", - "linux", - "win32", - "freebsd", - "openbsd", - "netbsd", - "sunos", - "android" + "linux" ], - "bin": { - "systeminformation": "lib/cli.js" - }, "engines": { - "node": ">=8.0.0" - }, - "funding": { - "type": "Buy me a coffee", - "url": "https://www.buymeacoffee.com/systeminfo" + "node": ">=18" } }, - "node_modules/three": { - "version": "0.181.2", - "resolved": "https://registry.npmjs.org/three/-/three-0.181.2.tgz", - "integrity": "sha512-k/CjiZ80bYss6Qs7/ex1TBlPD11whT9oKfT8oTGiHa34W4JRd1NiH/Tr1DbHWQ2/vMUypxksLnF2CfmlmM5XFQ==", - "license": "MIT" - }, - "node_modules/threejs-server": { - "resolved": "examples/threejs-server", - "link": true - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz", + "integrity": "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "node": ">=18" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz", + "integrity": "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": ">=18" } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz", + "integrity": "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=18" } }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz", + "integrity": "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=18" } }, - "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz", + "integrity": "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/tinyspy": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", - "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz", + "integrity": "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz", + "integrity": "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8.0" + "node": ">=18" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz", + "integrity": "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.6" + "node": ">=18" } }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz", + "integrity": "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==", + "cpu": [ + "x64" + ], "dev": true, - "bin": { - "nodetouch": "bin/nodetouch.js" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "node_modules/tsx/node_modules/esbuild": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", + "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", "dev": true, + "hasInstallScript": true, + "license": "MIT", "bin": { - "tree-kill": "cli.js" + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.1", + "@esbuild/android-arm": "0.27.1", + "@esbuild/android-arm64": "0.27.1", + "@esbuild/android-x64": "0.27.1", + "@esbuild/darwin-arm64": "0.27.1", + "@esbuild/darwin-x64": "0.27.1", + "@esbuild/freebsd-arm64": "0.27.1", + "@esbuild/freebsd-x64": "0.27.1", + "@esbuild/linux-arm": "0.27.1", + "@esbuild/linux-arm64": "0.27.1", + "@esbuild/linux-ia32": "0.27.1", + "@esbuild/linux-loong64": "0.27.1", + "@esbuild/linux-mips64el": "0.27.1", + "@esbuild/linux-ppc64": "0.27.1", + "@esbuild/linux-riscv64": "0.27.1", + "@esbuild/linux-s390x": "0.27.1", + "@esbuild/linux-x64": "0.27.1", + "@esbuild/netbsd-arm64": "0.27.1", + "@esbuild/netbsd-x64": "0.27.1", + "@esbuild/openbsd-arm64": "0.27.1", + "@esbuild/openbsd-x64": "0.27.1", + "@esbuild/openharmony-arm64": "0.27.1", + "@esbuild/sunos-x64": "0.27.1", + "@esbuild/win32-arm64": "0.27.1", + "@esbuild/win32-ia32": "0.27.1", + "@esbuild/win32-x64": "0.27.1" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, "node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", @@ -4602,6 +6226,26 @@ "node": ">=8" } }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 915a7b76..af9d5db6 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "./app-bridge": { "types": "./dist/src/app-bridge.d.ts", "default": "./dist/src/app-bridge.js" - } + }, + "./schema.json": "./dist/src/generated/schema.json" }, "files": [ "dist" @@ -31,7 +32,8 @@ "examples/*" ], "scripts": { - "build": "bun build.bun.ts", + "generate:schemas": "tsx scripts/generate-schemas.ts", + "build": "npm run generate:schemas && bun build.bun.ts", "prepack": "npm run build", "build:all": "npm run build && npm run examples:build", "test": "bun test", @@ -59,6 +61,8 @@ "husky": "^9.1.7", "nodemon": "^3.1.0", "prettier": "^3.6.2", + "ts-to-zod": "^5.1.0", + "tsx": "^4.21.0", "typedoc": "^0.28.14", "typescript": "^5.9.3" }, diff --git a/scripts/generate-schemas.ts b/scripts/generate-schemas.ts new file mode 100644 index 00000000..87bf5168 --- /dev/null +++ b/scripts/generate-schemas.ts @@ -0,0 +1,281 @@ +/** + * Schema Generation Script using ts-to-zod as a library + * + * This script generates Zod schemas from spec.types.ts and performs necessary + * post-processing for compatibility with this project. + * + * ## Why Post-Processing is Needed + * + * ts-to-zod is a powerful tool but has limitations that require post-processing: + * + * ### 1. Zod Import Path (`"zod"` → `"zod/v4"`) + * + * **Problem**: ts-to-zod generates `import { z } from "zod"` but this project + * uses the Zod v4 subpath import `"zod/v4"` for explicit version targeting. + * + * **Solution**: Replace the import path in the generated output. + * + * ### 2. External Type References (`z.any()` → actual schemas) + * + * **Problem**: ts-to-zod cannot resolve types imported from external packages. + * When it encounters types like `ContentBlock`, `CallToolResult`, `Implementation`, + * `RequestId`, and `Tool` from `@modelcontextprotocol/sdk`, it generates `z.any()` + * as a placeholder. + * + * **Solution**: Import the schemas from MCP SDK and remove the z.any() placeholders. + * + * ### 3. Index Signatures (`z.record().and()` → `z.looseObject()`) + * + * **Problem**: TypeScript index signatures like `[key: string]: unknown` are + * translated by ts-to-zod to `z.record(z.string(), z.unknown()).and(z.object({...}))`. + * This creates a `ZodIntersection` type which doesn't support `.extend()` etc. + * + * **Solution**: Replace the intersection pattern with `z.looseObject()`. + * + * ## Adding Schema Descriptions + * + * ts-to-zod supports `@description` JSDoc tags to generate `.describe()` calls: + * + * ```typescript + * interface MyType { + * /​** @description The user's full name *​/ + * name: string; + * } + * ``` + * + * Generates: `name: z.string().describe("The user's full name")` + * + * @see https://github.com/fabien0102/ts-to-zod + */ + +import { readFileSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { generate } from "ts-to-zod"; +import { toJSONSchema, type $ZodType } from "zod/v4/core"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const PROJECT_ROOT = join(__dirname, ".."); + +const SPEC_TYPES_FILE = join(PROJECT_ROOT, "src", "spec.types.ts"); +const GENERATED_DIR = join(PROJECT_ROOT, "src", "generated"); +const SCHEMA_OUTPUT_FILE = join(GENERATED_DIR, "schema.ts"); +const SCHEMA_TEST_OUTPUT_FILE = join(GENERATED_DIR, "schema.test.ts"); +const JSON_SCHEMA_OUTPUT_FILE = join(GENERATED_DIR, "schema.json"); + +/** + * External types from MCP SDK that ts-to-zod can't resolve. + * With PascalCase naming (via getSchemaName), generated placeholders match MCP SDK exports. + */ +const EXTERNAL_TYPE_SCHEMAS = [ + "ContentBlockSchema", + "CallToolResultSchema", + "ImplementationSchema", + "RequestIdSchema", + "ToolSchema", +]; + +async function main() { + console.log("🔧 Generating Zod schemas from spec.types.ts...\n"); + + const sourceText = readFileSync(SPEC_TYPES_FILE, "utf-8"); + + const result = generate({ + sourceText, + keepComments: true, + skipParseJSDoc: false, + // Generate PascalCase schema names: McpUiOpenLinkRequest → McpUiOpenLinkRequestSchema + getSchemaName: (typeName: string) => `${typeName}Schema`, + }); + + if (result.errors.length > 0) { + console.error("❌ Generation errors:"); + for (const error of result.errors) { + console.error(` - ${error}`); + } + process.exit(1); + } + + if (result.hasCircularDependencies) { + console.warn("⚠️ Warning: Circular dependencies detected in types"); + } + + let schemasContent = result.getZodSchemasFile("../spec.types.js"); + schemasContent = postProcess(schemasContent); + + writeFileSync(SCHEMA_OUTPUT_FILE, schemasContent, "utf-8"); + console.log(`✅ Written: ${SCHEMA_OUTPUT_FILE}`); + + const testsContent = result.getIntegrationTestFile( + "../spec.types.js", + "./schema.js", + ); + if (testsContent) { + const processedTests = postProcessTests(testsContent); + writeFileSync(SCHEMA_TEST_OUTPUT_FILE, processedTests, "utf-8"); + console.log(`✅ Written: ${SCHEMA_TEST_OUTPUT_FILE}`); + } + + // Generate JSON Schema from the Zod schemas + await generateJsonSchema(); + + console.log("\n🎉 Schema generation complete!"); +} + +/** + * Generate JSON Schema from the Zod schemas. + * Uses dynamic import to load the generated schemas after they're written. + */ +async function generateJsonSchema() { + // Dynamic import of the generated schemas + // tsx handles TypeScript imports at runtime + const schemas = await import("../src/generated/schema.js"); + + const jsonSchema: { + $schema: string; + $id: string; + title: string; + description: string; + $defs: Record; + } = { + $schema: "https://json-schema.org/draft/2020-12/schema", + $id: "https://modelcontextprotocol.io/ext-apps/schema.json", + title: "MCP Apps Protocol", + description: "JSON Schema for MCP Apps UI protocol messages", + $defs: {}, + }; + + // Convert each exported Zod schema to JSON Schema + for (const [name, schema] of Object.entries(schemas)) { + if ( + name.endsWith("Schema") && + typeof schema === "object" && + schema !== null + ) { + const typeName = name.replace(/Schema$/, ""); + try { + // Use unrepresentable: "any" to handle external types (MCP SDK schemas) + // that can't be directly represented in JSON Schema + jsonSchema.$defs[typeName] = toJSONSchema(schema as $ZodType, { + unrepresentable: "any", + }); + } catch (error) { + console.warn(`⚠️ Could not convert ${name} to JSON Schema: ${error}`); + } + } + } + + writeFileSync( + JSON_SCHEMA_OUTPUT_FILE, + JSON.stringify(jsonSchema, null, 2) + "\n", + "utf-8", + ); + console.log(`✅ Written: ${JSON_SCHEMA_OUTPUT_FILE}`); +} + +/** + * Post-process generated schemas for project compatibility. + */ +function postProcess(content: string): string { + // 1. Update import to use zod/v4 + content = content.replace( + 'import { z } from "zod";', + 'import { z } from "zod/v4";', + ); + + // 2. Add MCP SDK schema imports + const mcpImports = EXTERNAL_TYPE_SCHEMAS.join(",\n "); + content = content.replace( + 'import { z } from "zod/v4";', + `import { z } from "zod/v4"; +import { + ${mcpImports}, +} from "@modelcontextprotocol/sdk/types.js";`, + ); + + // 3. Remove z.any() placeholders for external types (now imported from MCP SDK) + for (const schema of EXTERNAL_TYPE_SCHEMAS) { + content = content.replace( + new RegExp(`(?:export )?const ${schema} = z\\.any\\(\\);\\n?`, "g"), + "", + ); + } + + // 4. Replace z.record().and(z.object({...})) with z.looseObject({...}) + // Uses brace-counting to handle nested objects correctly. + content = replaceRecordAndWithLooseObject(content); + + // 5. Add header comment + content = content.replace( + "// Generated by ts-to-zod", + `// Generated by ts-to-zod +// Post-processed for Zod v4 and MCP SDK compatibility +// Run: npm run generate:schemas`, + ); + + return content; +} + +/** + * Replace z.record(z.string(), z.unknown()).and(z.object({...})) with z.looseObject({...}) + * Uses brace-counting to handle nested objects correctly. + */ +function replaceRecordAndWithLooseObject(content: string): string { + const pattern = "z.record(z.string(), z.unknown()).and(z.object({"; + let result = content; + let startIndex = 0; + + while (true) { + const matchStart = result.indexOf(pattern, startIndex); + if (matchStart === -1) break; + + // Find the matching closing brace for z.object({ + const objectStart = matchStart + pattern.length; + let braceCount = 1; + let i = objectStart; + + while (i < result.length && braceCount > 0) { + if (result[i] === "{") braceCount++; + else if (result[i] === "}") braceCount--; + i++; + } + + // i now points after the closing } of z.object({...}) + // Check if followed by )) + if (result.slice(i, i + 2) === "))") { + const objectContent = result.slice(objectStart, i - 1); + const replacement = `z.looseObject({${objectContent}})`; + result = result.slice(0, matchStart) + replacement + result.slice(i + 2); + startIndex = matchStart + replacement.length; + } else { + startIndex = i; + } + } + + return result; +} + +/** + * Post-process generated integration tests. + */ +function postProcessTests(content: string): string { + content = content.replace( + 'import { z } from "zod";', + 'import { z } from "zod/v4";', + ); + + content = content.replace( + "// Generated by ts-to-zod", + `// Generated by ts-to-zod +// Integration tests verifying schemas match TypeScript types +// Run: npm run generate:schemas`, + ); + + return content; +} + +main().catch((error) => { + console.error("❌ Schema generation failed:", error); + process.exit(1); +}); diff --git a/src/generated/schema.json b/src/generated/schema.json new file mode 100644 index 00000000..b51e23bc --- /dev/null +++ b/src/generated/schema.json @@ -0,0 +1,2151 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://modelcontextprotocol.io/ext-apps/schema.json", + "title": "MCP Apps Protocol", + "description": "JSON Schema for MCP Apps UI protocol messages", + "$defs": { + "McpUiAppCapabilities": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "experimental": { + "description": "Experimental features (structure TBD).", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "tools": { + "description": "App exposes MCP-style tools that the host can call.", + "type": "object", + "properties": { + "listChanged": { + "description": "App supports tools/list_changed notifications.", + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "McpUiDisplayMode": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Display mode for UI presentation.", + "anyOf": [ + { + "type": "string", + "const": "inline" + }, + { + "type": "string", + "const": "fullscreen" + }, + { + "type": "string", + "const": "pip" + } + ] + }, + "McpUiHostCapabilities": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "experimental": { + "description": "Experimental features (structure TBD).", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "openLinks": { + "description": "Host supports opening external URLs.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "serverTools": { + "description": "Host can proxy tool calls to the MCP server.", + "type": "object", + "properties": { + "listChanged": { + "description": "Host supports tools/list_changed notifications.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "serverResources": { + "description": "Host can proxy resource reads to the MCP server.", + "type": "object", + "properties": { + "listChanged": { + "description": "Host supports resources/list_changed notifications.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "logging": { + "description": "Host accepts log messages.", + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "McpUiHostContextChangedNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/host-context-changed" + }, + "params": { + "description": "Partial context update containing only changed fields.", + "type": "object", + "properties": { + "toolInfo": { + "description": "Metadata of the tool call that instantiated this App.", + "type": "object", + "properties": { + "id": { + "description": "JSON-RPC id of the tools/call request.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + ] + }, + "tool": { + "description": "Tool definition including name, inputSchema, etc.", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "description": { + "type": "string" + }, + "inputSchema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "object" + }, + "properties": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["type"], + "additionalProperties": {} + }, + "outputSchema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "object" + }, + "properties": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["type"], + "additionalProperties": {} + }, + "annotations": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "readOnlyHint": { + "type": "boolean" + }, + "destructiveHint": { + "type": "boolean" + }, + "idempotentHint": { + "type": "boolean" + }, + "openWorldHint": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "execution": { + "type": "object", + "properties": { + "taskSupport": { + "type": "string", + "enum": ["required", "optional", "forbidden"] + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["name", "inputSchema"], + "additionalProperties": false + } + }, + "required": ["id", "tool"], + "additionalProperties": false + }, + "theme": { + "description": "Current color theme preference.", + "anyOf": [ + { + "type": "string", + "const": "light" + }, + { + "type": "string", + "const": "dark" + } + ] + }, + "displayMode": { + "description": "How the UI is currently displayed.", + "anyOf": [ + { + "type": "string", + "const": "inline" + }, + { + "type": "string", + "const": "fullscreen" + }, + { + "type": "string", + "const": "pip" + } + ] + }, + "availableDisplayModes": { + "description": "Display modes the host supports.", + "type": "array", + "items": { + "type": "string" + } + }, + "viewport": { + "description": "Current and maximum dimensions available to the UI.", + "type": "object", + "properties": { + "width": { + "description": "Current viewport width in pixels.", + "type": "number" + }, + "height": { + "description": "Current viewport height in pixels.", + "type": "number" + }, + "maxHeight": { + "description": "Maximum available height in pixels (if constrained).", + "type": "number" + }, + "maxWidth": { + "description": "Maximum available width in pixels (if constrained).", + "type": "number" + } + }, + "required": ["width", "height"], + "additionalProperties": false + }, + "locale": { + "description": "User's language and region preference in BCP 47 format.", + "type": "string" + }, + "timeZone": { + "description": "User's timezone in IANA format.", + "type": "string" + }, + "userAgent": { + "description": "Host application identifier.", + "type": "string" + }, + "platform": { + "description": "Platform type for responsive design decisions.", + "anyOf": [ + { + "type": "string", + "const": "web" + }, + { + "type": "string", + "const": "desktop" + }, + { + "type": "string", + "const": "mobile" + } + ] + }, + "deviceCapabilities": { + "description": "Device input capabilities.", + "type": "object", + "properties": { + "touch": { + "description": "Whether the device supports touch input.", + "type": "boolean" + }, + "hover": { + "description": "Whether the device supports hover interactions.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "safeAreaInsets": { + "description": "Mobile safe area boundaries in pixels.", + "type": "object", + "properties": { + "top": { + "description": "Top safe area inset in pixels.", + "type": "number" + }, + "right": { + "description": "Right safe area inset in pixels.", + "type": "number" + }, + "bottom": { + "description": "Bottom safe area inset in pixels.", + "type": "number" + }, + "left": { + "description": "Left safe area inset in pixels.", + "type": "number" + } + }, + "required": ["top", "right", "bottom", "left"], + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiHostContext": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "toolInfo": { + "description": "Metadata of the tool call that instantiated this App.", + "type": "object", + "properties": { + "id": { + "description": "JSON-RPC id of the tools/call request.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + ] + }, + "tool": { + "description": "Tool definition including name, inputSchema, etc.", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "description": { + "type": "string" + }, + "inputSchema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "object" + }, + "properties": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["type"], + "additionalProperties": {} + }, + "outputSchema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "object" + }, + "properties": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["type"], + "additionalProperties": {} + }, + "annotations": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "readOnlyHint": { + "type": "boolean" + }, + "destructiveHint": { + "type": "boolean" + }, + "idempotentHint": { + "type": "boolean" + }, + "openWorldHint": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "execution": { + "type": "object", + "properties": { + "taskSupport": { + "type": "string", + "enum": ["required", "optional", "forbidden"] + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["name", "inputSchema"], + "additionalProperties": false + } + }, + "required": ["id", "tool"], + "additionalProperties": false + }, + "theme": { + "description": "Current color theme preference.", + "anyOf": [ + { + "type": "string", + "const": "light" + }, + { + "type": "string", + "const": "dark" + } + ] + }, + "displayMode": { + "description": "How the UI is currently displayed.", + "anyOf": [ + { + "type": "string", + "const": "inline" + }, + { + "type": "string", + "const": "fullscreen" + }, + { + "type": "string", + "const": "pip" + } + ] + }, + "availableDisplayModes": { + "description": "Display modes the host supports.", + "type": "array", + "items": { + "type": "string" + } + }, + "viewport": { + "description": "Current and maximum dimensions available to the UI.", + "type": "object", + "properties": { + "width": { + "description": "Current viewport width in pixels.", + "type": "number" + }, + "height": { + "description": "Current viewport height in pixels.", + "type": "number" + }, + "maxHeight": { + "description": "Maximum available height in pixels (if constrained).", + "type": "number" + }, + "maxWidth": { + "description": "Maximum available width in pixels (if constrained).", + "type": "number" + } + }, + "required": ["width", "height"], + "additionalProperties": false + }, + "locale": { + "description": "User's language and region preference in BCP 47 format.", + "type": "string" + }, + "timeZone": { + "description": "User's timezone in IANA format.", + "type": "string" + }, + "userAgent": { + "description": "Host application identifier.", + "type": "string" + }, + "platform": { + "description": "Platform type for responsive design decisions.", + "anyOf": [ + { + "type": "string", + "const": "web" + }, + { + "type": "string", + "const": "desktop" + }, + { + "type": "string", + "const": "mobile" + } + ] + }, + "deviceCapabilities": { + "description": "Device input capabilities.", + "type": "object", + "properties": { + "touch": { + "description": "Whether the device supports touch input.", + "type": "boolean" + }, + "hover": { + "description": "Whether the device supports hover interactions.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "safeAreaInsets": { + "description": "Mobile safe area boundaries in pixels.", + "type": "object", + "properties": { + "top": { + "description": "Top safe area inset in pixels.", + "type": "number" + }, + "right": { + "description": "Right safe area inset in pixels.", + "type": "number" + }, + "bottom": { + "description": "Bottom safe area inset in pixels.", + "type": "number" + }, + "left": { + "description": "Left safe area inset in pixels.", + "type": "number" + } + }, + "required": ["top", "right", "bottom", "left"], + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "McpUiInitializeRequest": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/initialize" + }, + "params": { + "type": "object", + "properties": { + "appInfo": { + "description": "App identification (name and version).", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "version": { + "type": "string" + }, + "websiteUrl": { + "type": "string" + } + }, + "required": ["name", "version"], + "additionalProperties": false + }, + "appCapabilities": { + "description": "Features and capabilities this app provides.", + "type": "object", + "properties": { + "experimental": { + "description": "Experimental features (structure TBD).", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "tools": { + "description": "App exposes MCP-style tools that the host can call.", + "type": "object", + "properties": { + "listChanged": { + "description": "App supports tools/list_changed notifications.", + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "protocolVersion": { + "description": "Protocol version this app supports.", + "type": "string" + } + }, + "required": ["appInfo", "appCapabilities", "protocolVersion"], + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiInitializeResult": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "protocolVersion": { + "description": "Negotiated protocol version string (e.g., \"2025-11-21\").", + "type": "string" + }, + "hostInfo": { + "description": "Host application identification and version.", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "version": { + "type": "string" + }, + "websiteUrl": { + "type": "string" + } + }, + "required": ["name", "version"], + "additionalProperties": false + }, + "hostCapabilities": { + "description": "Features and capabilities provided by the host.", + "type": "object", + "properties": { + "experimental": { + "description": "Experimental features (structure TBD).", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "openLinks": { + "description": "Host supports opening external URLs.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "serverTools": { + "description": "Host can proxy tool calls to the MCP server.", + "type": "object", + "properties": { + "listChanged": { + "description": "Host supports tools/list_changed notifications.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "serverResources": { + "description": "Host can proxy resource reads to the MCP server.", + "type": "object", + "properties": { + "listChanged": { + "description": "Host supports resources/list_changed notifications.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "logging": { + "description": "Host accepts log messages.", + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "hostContext": { + "description": "Rich context about the host environment.", + "type": "object", + "properties": { + "toolInfo": { + "description": "Metadata of the tool call that instantiated this App.", + "type": "object", + "properties": { + "id": { + "description": "JSON-RPC id of the tools/call request.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + ] + }, + "tool": { + "description": "Tool definition including name, inputSchema, etc.", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "description": { + "type": "string" + }, + "inputSchema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "object" + }, + "properties": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["type"], + "additionalProperties": {} + }, + "outputSchema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "object" + }, + "properties": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "required": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["type"], + "additionalProperties": {} + }, + "annotations": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "readOnlyHint": { + "type": "boolean" + }, + "destructiveHint": { + "type": "boolean" + }, + "idempotentHint": { + "type": "boolean" + }, + "openWorldHint": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "execution": { + "type": "object", + "properties": { + "taskSupport": { + "type": "string", + "enum": ["required", "optional", "forbidden"] + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["name", "inputSchema"], + "additionalProperties": false + } + }, + "required": ["id", "tool"], + "additionalProperties": false + }, + "theme": { + "description": "Current color theme preference.", + "anyOf": [ + { + "type": "string", + "const": "light" + }, + { + "type": "string", + "const": "dark" + } + ] + }, + "displayMode": { + "description": "How the UI is currently displayed.", + "anyOf": [ + { + "type": "string", + "const": "inline" + }, + { + "type": "string", + "const": "fullscreen" + }, + { + "type": "string", + "const": "pip" + } + ] + }, + "availableDisplayModes": { + "description": "Display modes the host supports.", + "type": "array", + "items": { + "type": "string" + } + }, + "viewport": { + "description": "Current and maximum dimensions available to the UI.", + "type": "object", + "properties": { + "width": { + "description": "Current viewport width in pixels.", + "type": "number" + }, + "height": { + "description": "Current viewport height in pixels.", + "type": "number" + }, + "maxHeight": { + "description": "Maximum available height in pixels (if constrained).", + "type": "number" + }, + "maxWidth": { + "description": "Maximum available width in pixels (if constrained).", + "type": "number" + } + }, + "required": ["width", "height"], + "additionalProperties": false + }, + "locale": { + "description": "User's language and region preference in BCP 47 format.", + "type": "string" + }, + "timeZone": { + "description": "User's timezone in IANA format.", + "type": "string" + }, + "userAgent": { + "description": "Host application identifier.", + "type": "string" + }, + "platform": { + "description": "Platform type for responsive design decisions.", + "anyOf": [ + { + "type": "string", + "const": "web" + }, + { + "type": "string", + "const": "desktop" + }, + { + "type": "string", + "const": "mobile" + } + ] + }, + "deviceCapabilities": { + "description": "Device input capabilities.", + "type": "object", + "properties": { + "touch": { + "description": "Whether the device supports touch input.", + "type": "boolean" + }, + "hover": { + "description": "Whether the device supports hover interactions.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "safeAreaInsets": { + "description": "Mobile safe area boundaries in pixels.", + "type": "object", + "properties": { + "top": { + "description": "Top safe area inset in pixels.", + "type": "number" + }, + "right": { + "description": "Right safe area inset in pixels.", + "type": "number" + }, + "bottom": { + "description": "Bottom safe area inset in pixels.", + "type": "number" + }, + "left": { + "description": "Left safe area inset in pixels.", + "type": "number" + } + }, + "required": ["top", "right", "bottom", "left"], + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "required": [ + "protocolVersion", + "hostInfo", + "hostCapabilities", + "hostContext" + ], + "additionalProperties": {} + }, + "McpUiInitializedNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/initialized" + }, + "params": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "required": ["method"], + "additionalProperties": false + }, + "McpUiMessageRequest": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/message" + }, + "params": { + "type": "object", + "properties": { + "role": { + "description": "Message role, currently only \"user\" is supported.", + "type": "string", + "const": "user" + }, + "content": { + "description": "Message content blocks (text, image, etc.).", + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "text": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "text"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "data": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "data", "mimeType"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "data": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "data", "mimeType"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "uri": { + "type": "string" + }, + "description": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "properties": {}, + "additionalProperties": {} + }, + "type": { + "type": "string", + "const": "resource_link" + } + }, + "required": ["name", "uri", "type"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "resource" + }, + "resource": { + "anyOf": [ + { + "type": "object", + "properties": { + "uri": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "text": { + "type": "string" + } + }, + "required": ["uri", "text"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "uri": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "blob": { + "type": "string" + } + }, + "required": ["uri", "blob"], + "additionalProperties": false + } + ] + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "resource"], + "additionalProperties": false + } + ] + } + } + }, + "required": ["role", "content"], + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiMessageResult": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "isError": { + "description": "True if the host rejected or failed to deliver the message.", + "type": "boolean" + } + }, + "additionalProperties": {} + }, + "McpUiOpenLinkRequest": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/open-link" + }, + "params": { + "type": "object", + "properties": { + "url": { + "description": "URL to open in the host's browser", + "type": "string" + } + }, + "required": ["url"], + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiOpenLinkResult": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "isError": { + "description": "True if the host failed to open the URL (e.g., due to security policy).", + "type": "boolean" + } + }, + "additionalProperties": {} + }, + "McpUiResourceCsp": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "connectDomains": { + "description": "Origins for network requests (fetch/XHR/WebSocket).", + "type": "array", + "items": { + "type": "string" + } + }, + "resourceDomains": { + "description": "Origins for static resources (scripts, images, styles, fonts).", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "McpUiResourceMeta": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "csp": { + "description": "Content Security Policy configuration.", + "type": "object", + "properties": { + "connectDomains": { + "description": "Origins for network requests (fetch/XHR/WebSocket).", + "type": "array", + "items": { + "type": "string" + } + }, + "resourceDomains": { + "description": "Origins for static resources (scripts, images, styles, fonts).", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "domain": { + "description": "Dedicated origin for widget sandbox.", + "type": "string" + }, + "prefersBorder": { + "description": "Visual boundary preference - true if UI prefers a visible border.", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "McpUiResourceTeardownRequest": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/resource-teardown" + }, + "params": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiResourceTeardownResult": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "McpUiSandboxProxyReadyNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/sandbox-proxy-ready" + }, + "params": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiSandboxResourceReadyNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/sandbox-resource-ready" + }, + "params": { + "type": "object", + "properties": { + "html": { + "description": "HTML content to load into the inner iframe.", + "type": "string" + }, + "sandbox": { + "description": "Optional override for the inner iframe's sandbox attribute.", + "type": "string" + }, + "csp": { + "description": "CSP configuration from resource metadata.", + "type": "object", + "properties": { + "connectDomains": { + "description": "Origins for network requests (fetch/XHR/WebSocket).", + "type": "array", + "items": { + "type": "string" + } + }, + "resourceDomains": { + "description": "Origins for static resources (scripts, images, styles, fonts).", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "required": ["html"], + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiSizeChangedNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/size-changed" + }, + "params": { + "type": "object", + "properties": { + "width": { + "description": "New width in pixels.", + "type": "number" + }, + "height": { + "description": "New height in pixels.", + "type": "number" + } + }, + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiTheme": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Color theme preference for the host environment.", + "anyOf": [ + { + "type": "string", + "const": "light" + }, + { + "type": "string", + "const": "dark" + } + ] + }, + "McpUiToolInputNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/tool-input" + }, + "params": { + "type": "object", + "properties": { + "arguments": { + "description": "Complete tool call arguments as key-value pairs.", + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "description": "Complete tool call arguments as key-value pairs." + } + } + }, + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiToolInputPartialNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/tool-input-partial" + }, + "params": { + "type": "object", + "properties": { + "arguments": { + "description": "Partial tool call arguments (incomplete, may change).", + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "description": "Partial tool call arguments (incomplete, may change)." + } + } + }, + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiToolResultNotification": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/notifications/tool-result" + }, + "params": { + "description": "Standard MCP tool execution result.", + "type": "object", + "properties": { + "_meta": { + "type": "object", + "properties": { + "io.modelcontextprotocol/related-task": { + "type": "object", + "properties": { + "taskId": { + "type": "string" + } + }, + "required": ["taskId"], + "additionalProperties": {} + } + }, + "additionalProperties": {} + }, + "content": { + "default": [], + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "text": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "text"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "data": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "data", "mimeType"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "data": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "data", "mimeType"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "uri": { + "type": "string" + }, + "description": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "properties": {}, + "additionalProperties": {} + }, + "type": { + "type": "string", + "const": "resource_link" + } + }, + "required": ["name", "uri", "type"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "resource" + }, + "resource": { + "anyOf": [ + { + "type": "object", + "properties": { + "uri": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "text": { + "type": "string" + } + }, + "required": ["uri", "text"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "uri": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "blob": { + "type": "string" + } + }, + "required": ["uri", "blob"], + "additionalProperties": false + } + ] + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "resource"], + "additionalProperties": false + } + ] + } + }, + "structuredContent": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "isError": { + "type": "boolean" + } + }, + "required": ["content"], + "additionalProperties": {} + } + }, + "required": ["method", "params"], + "additionalProperties": false + } + } +} diff --git a/src/generated/schema.test.ts b/src/generated/schema.test.ts new file mode 100644 index 00000000..5a2e3a60 --- /dev/null +++ b/src/generated/schema.test.ts @@ -0,0 +1,219 @@ +// Generated by ts-to-zod +// Integration tests verifying schemas match TypeScript types +// Run: npm run generate:schemas +import { z } from "zod/v4"; + +import * as spec from "../spec.types.js"; +import * as generated from "./schema.js"; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function expectType(_: T) { + /* noop */ +} + +export type McpUiThemeSchemaInferredType = z.infer< + typeof generated.McpUiThemeSchema +>; + +export type McpUiDisplayModeSchemaInferredType = z.infer< + typeof generated.McpUiDisplayModeSchema +>; + +export type McpUiOpenLinkRequestSchemaInferredType = z.infer< + typeof generated.McpUiOpenLinkRequestSchema +>; + +export type McpUiOpenLinkResultSchemaInferredType = z.infer< + typeof generated.McpUiOpenLinkResultSchema +>; + +export type McpUiMessageResultSchemaInferredType = z.infer< + typeof generated.McpUiMessageResultSchema +>; + +export type McpUiSandboxProxyReadyNotificationSchemaInferredType = z.infer< + typeof generated.McpUiSandboxProxyReadyNotificationSchema +>; + +export type McpUiSandboxResourceReadyNotificationSchemaInferredType = z.infer< + typeof generated.McpUiSandboxResourceReadyNotificationSchema +>; + +export type McpUiSizeChangedNotificationSchemaInferredType = z.infer< + typeof generated.McpUiSizeChangedNotificationSchema +>; + +export type McpUiToolInputNotificationSchemaInferredType = z.infer< + typeof generated.McpUiToolInputNotificationSchema +>; + +export type McpUiToolInputPartialNotificationSchemaInferredType = z.infer< + typeof generated.McpUiToolInputPartialNotificationSchema +>; + +export type McpUiResourceTeardownRequestSchemaInferredType = z.infer< + typeof generated.McpUiResourceTeardownRequestSchema +>; + +export type McpUiResourceTeardownResultSchemaInferredType = z.infer< + typeof generated.McpUiResourceTeardownResultSchema +>; + +export type McpUiHostCapabilitiesSchemaInferredType = z.infer< + typeof generated.McpUiHostCapabilitiesSchema +>; + +export type McpUiAppCapabilitiesSchemaInferredType = z.infer< + typeof generated.McpUiAppCapabilitiesSchema +>; + +export type McpUiInitializedNotificationSchemaInferredType = z.infer< + typeof generated.McpUiInitializedNotificationSchema +>; + +export type McpUiResourceCspSchemaInferredType = z.infer< + typeof generated.McpUiResourceCspSchema +>; + +export type McpUiResourceMetaSchemaInferredType = z.infer< + typeof generated.McpUiResourceMetaSchema +>; + +export type McpUiMessageRequestSchemaInferredType = z.infer< + typeof generated.McpUiMessageRequestSchema +>; + +export type McpUiToolResultNotificationSchemaInferredType = z.infer< + typeof generated.McpUiToolResultNotificationSchema +>; + +export type McpUiHostContextSchemaInferredType = z.infer< + typeof generated.McpUiHostContextSchema +>; + +export type McpUiHostContextChangedNotificationSchemaInferredType = z.infer< + typeof generated.McpUiHostContextChangedNotificationSchema +>; + +export type McpUiInitializeRequestSchemaInferredType = z.infer< + typeof generated.McpUiInitializeRequestSchema +>; + +export type McpUiInitializeResultSchemaInferredType = z.infer< + typeof generated.McpUiInitializeResultSchema +>; + +expectType({} as McpUiThemeSchemaInferredType); +expectType({} as spec.McpUiTheme); +expectType({} as McpUiDisplayModeSchemaInferredType); +expectType({} as spec.McpUiDisplayMode); +expectType( + {} as McpUiOpenLinkRequestSchemaInferredType, +); +expectType( + {} as spec.McpUiOpenLinkRequest, +); +expectType( + {} as McpUiOpenLinkResultSchemaInferredType, +); +expectType( + {} as spec.McpUiOpenLinkResult, +); +expectType({} as McpUiMessageResultSchemaInferredType); +expectType({} as spec.McpUiMessageResult); +expectType( + {} as McpUiSandboxProxyReadyNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiSandboxProxyReadyNotification, +); +expectType( + {} as McpUiSandboxResourceReadyNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiSandboxResourceReadyNotification, +); +expectType( + {} as McpUiSizeChangedNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiSizeChangedNotification, +); +expectType( + {} as McpUiToolInputNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiToolInputNotification, +); +expectType( + {} as McpUiToolInputPartialNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiToolInputPartialNotification, +); +expectType( + {} as McpUiResourceTeardownRequestSchemaInferredType, +); +expectType( + {} as spec.McpUiResourceTeardownRequest, +); +expectType( + {} as McpUiResourceTeardownResultSchemaInferredType, +); +expectType( + {} as spec.McpUiResourceTeardownResult, +); +expectType( + {} as McpUiHostCapabilitiesSchemaInferredType, +); +expectType( + {} as spec.McpUiHostCapabilities, +); +expectType( + {} as McpUiAppCapabilitiesSchemaInferredType, +); +expectType( + {} as spec.McpUiAppCapabilities, +); +expectType( + {} as McpUiInitializedNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiInitializedNotification, +); +expectType({} as McpUiResourceCspSchemaInferredType); +expectType({} as spec.McpUiResourceCsp); +expectType({} as McpUiResourceMetaSchemaInferredType); +expectType({} as spec.McpUiResourceMeta); +expectType( + {} as McpUiMessageRequestSchemaInferredType, +); +expectType( + {} as spec.McpUiMessageRequest, +); +expectType( + {} as McpUiToolResultNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiToolResultNotification, +); +expectType({} as McpUiHostContextSchemaInferredType); +expectType({} as spec.McpUiHostContext); +expectType( + {} as McpUiHostContextChangedNotificationSchemaInferredType, +); +expectType( + {} as spec.McpUiHostContextChangedNotification, +); +expectType( + {} as McpUiInitializeRequestSchemaInferredType, +); +expectType( + {} as spec.McpUiInitializeRequest, +); +expectType( + {} as McpUiInitializeResultSchemaInferredType, +); +expectType( + {} as spec.McpUiInitializeResult, +); diff --git a/src/generated/schema.ts b/src/generated/schema.ts new file mode 100644 index 00000000..1b181afa --- /dev/null +++ b/src/generated/schema.ts @@ -0,0 +1,467 @@ +// Generated by ts-to-zod +// Post-processed for Zod v4 and MCP SDK compatibility +// Run: npm run generate:schemas +import { z } from "zod/v4"; +import { + ContentBlockSchema, + CallToolResultSchema, + ImplementationSchema, + RequestIdSchema, + ToolSchema, +} from "@modelcontextprotocol/sdk/types.js"; + +/** + * @description Color theme preference for the host environment. + */ +export const McpUiThemeSchema = z + .union([z.literal("light"), z.literal("dark")]) + .describe("Color theme preference for the host environment."); + +/** + * @description Display mode for UI presentation. + */ +export const McpUiDisplayModeSchema = z + .union([z.literal("inline"), z.literal("fullscreen"), z.literal("pip")]) + .describe("Display mode for UI presentation."); + +/** + * @description Request to open an external URL in the host's default browser. + * @see {@link app.App.sendOpenLink} for the method that sends this request + */ +export const McpUiOpenLinkRequestSchema = z.object({ + method: z.literal("ui/open-link"), + params: z.object({ + /** @description URL to open in the host's browser */ + url: z.string().describe("URL to open in the host's browser"), + }), +}); + +/** + * @description Result from opening a URL. + * @see {@link McpUiOpenLinkRequest} + */ +export const McpUiOpenLinkResultSchema = z.looseObject({ + /** @description True if the host failed to open the URL (e.g., due to security policy). */ + isError: z + .boolean() + .optional() + .describe( + "True if the host failed to open the URL (e.g., due to security policy).", + ), +}); + +/** + * @description Result from sending a message. + * @see {@link McpUiMessageRequest} + */ +export const McpUiMessageResultSchema = z.looseObject({ + /** @description True if the host rejected or failed to deliver the message. */ + isError: z + .boolean() + .optional() + .describe("True if the host rejected or failed to deliver the message."), +}); + +/** + * @description Notification that the sandbox proxy iframe is ready to receive content. + * @internal + * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy + */ +export const McpUiSandboxProxyReadyNotificationSchema = z.object({ + method: z.literal("ui/notifications/sandbox-proxy-ready"), + params: z.object({}), +}); + +/** + * @description Notification containing HTML resource for the sandbox proxy to load. + * @internal + * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy + */ +export const McpUiSandboxResourceReadyNotificationSchema = z.object({ + method: z.literal("ui/notifications/sandbox-resource-ready"), + params: z.object({ + /** @description HTML content to load into the inner iframe. */ + html: z.string().describe("HTML content to load into the inner iframe."), + /** @description Optional override for the inner iframe's sandbox attribute. */ + sandbox: z + .string() + .optional() + .describe("Optional override for the inner iframe's sandbox attribute."), + /** @description CSP configuration from resource metadata. */ + csp: z + .object({ + /** @description Origins for network requests (fetch/XHR/WebSocket). */ + connectDomains: z + .array(z.string()) + .optional() + .describe("Origins for network requests (fetch/XHR/WebSocket)."), + /** @description Origins for static resources (scripts, images, styles, fonts). */ + resourceDomains: z + .array(z.string()) + .optional() + .describe( + "Origins for static resources (scripts, images, styles, fonts).", + ), + }) + .optional() + .describe("CSP configuration from resource metadata."), + }), +}); + +/** + * @description Notification of UI size changes (bidirectional: Guest <-> Host). + * @see {@link app.App.sendSizeChanged} for the method to send this from Guest UI + */ +export const McpUiSizeChangedNotificationSchema = z.object({ + method: z.literal("ui/notifications/size-changed"), + params: z.object({ + /** @description New width in pixels. */ + width: z.number().optional().describe("New width in pixels."), + /** @description New height in pixels. */ + height: z.number().optional().describe("New height in pixels."), + }), +}); + +/** + * @description Notification containing complete tool arguments (Host -> Guest UI). + */ +export const McpUiToolInputNotificationSchema = z.object({ + method: z.literal("ui/notifications/tool-input"), + params: z.object({ + /** @description Complete tool call arguments as key-value pairs. */ + arguments: z + .record( + z.string(), + z + .unknown() + .describe("Complete tool call arguments as key-value pairs."), + ) + .optional() + .describe("Complete tool call arguments as key-value pairs."), + }), +}); + +/** + * @description Notification containing partial/streaming tool arguments (Host -> Guest UI). + */ +export const McpUiToolInputPartialNotificationSchema = z.object({ + method: z.literal("ui/notifications/tool-input-partial"), + params: z.object({ + /** @description Partial tool call arguments (incomplete, may change). */ + arguments: z + .record( + z.string(), + z + .unknown() + .describe("Partial tool call arguments (incomplete, may change)."), + ) + .optional() + .describe("Partial tool call arguments (incomplete, may change)."), + }), +}); + +/** + * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). + * @see {@link app-bridge.AppBridge.sendResourceTeardown} for the host method that sends this + */ +export const McpUiResourceTeardownRequestSchema = z.object({ + method: z.literal("ui/resource-teardown"), + params: z.object({}), +}); + +/** + * @description Result from graceful shutdown request. + * @see {@link McpUiResourceTeardownRequest} + */ +export const McpUiResourceTeardownResultSchema = z.record( + z.string(), + z.unknown(), +); + +/** + * @description Capabilities supported by the host application. + * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities + */ +export const McpUiHostCapabilitiesSchema = z.object({ + /** @description Experimental features (structure TBD). */ + experimental: z + .object({}) + .optional() + .describe("Experimental features (structure TBD)."), + /** @description Host supports opening external URLs. */ + openLinks: z + .object({}) + .optional() + .describe("Host supports opening external URLs."), + /** @description Host can proxy tool calls to the MCP server. */ + serverTools: z + .object({ + /** @description Host supports tools/list_changed notifications. */ + listChanged: z + .boolean() + .optional() + .describe("Host supports tools/list_changed notifications."), + }) + .optional() + .describe("Host can proxy tool calls to the MCP server."), + /** @description Host can proxy resource reads to the MCP server. */ + serverResources: z + .object({ + /** @description Host supports resources/list_changed notifications. */ + listChanged: z + .boolean() + .optional() + .describe("Host supports resources/list_changed notifications."), + }) + .optional() + .describe("Host can proxy resource reads to the MCP server."), + /** @description Host accepts log messages. */ + logging: z.object({}).optional().describe("Host accepts log messages."), +}); + +/** + * @description Capabilities provided by the Guest UI (App). + * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities + */ +export const McpUiAppCapabilitiesSchema = z.object({ + /** @description Experimental features (structure TBD). */ + experimental: z + .object({}) + .optional() + .describe("Experimental features (structure TBD)."), + /** @description App exposes MCP-style tools that the host can call. */ + tools: z + .object({ + /** @description App supports tools/list_changed notifications. */ + listChanged: z + .boolean() + .optional() + .describe("App supports tools/list_changed notifications."), + }) + .optional() + .describe("App exposes MCP-style tools that the host can call."), +}); + +/** + * @description Notification that Guest UI has completed initialization (Guest UI -> Host). + * @see {@link app.App.connect} for the method that sends this notification + */ +export const McpUiInitializedNotificationSchema = z.object({ + method: z.literal("ui/notifications/initialized"), + params: z.object({}).optional(), +}); + +/** + * @description Content Security Policy configuration for UI resources. + */ +export const McpUiResourceCspSchema = z.object({ + /** @description Origins for network requests (fetch/XHR/WebSocket). */ + connectDomains: z + .array(z.string()) + .optional() + .describe("Origins for network requests (fetch/XHR/WebSocket)."), + /** @description Origins for static resources (scripts, images, styles, fonts). */ + resourceDomains: z + .array(z.string()) + .optional() + .describe("Origins for static resources (scripts, images, styles, fonts)."), +}); + +/** + * @description UI Resource metadata for security and rendering configuration. + */ +export const McpUiResourceMetaSchema = z.object({ + /** @description Content Security Policy configuration. */ + csp: McpUiResourceCspSchema.optional().describe( + "Content Security Policy configuration.", + ), + /** @description Dedicated origin for widget sandbox. */ + domain: z + .string() + .optional() + .describe("Dedicated origin for widget sandbox."), + /** @description Visual boundary preference - true if UI prefers a visible border. */ + prefersBorder: z + .boolean() + .optional() + .describe( + "Visual boundary preference - true if UI prefers a visible border.", + ), +}); + +/** + * @description Request to send a message to the host's chat interface. + * @see {@link app.App.sendMessage} for the method that sends this request + */ +export const McpUiMessageRequestSchema = z.object({ + method: z.literal("ui/message"), + params: z.object({ + /** @description Message role, currently only "user" is supported. */ + role: z + .literal("user") + .describe('Message role, currently only "user" is supported.'), + /** @description Message content blocks (text, image, etc.). */ + content: z + .array(ContentBlockSchema) + .describe("Message content blocks (text, image, etc.)."), + }), +}); + +/** + * @description Notification containing tool execution result (Host -> Guest UI). + */ +export const McpUiToolResultNotificationSchema = z.object({ + method: z.literal("ui/notifications/tool-result"), + /** @description Standard MCP tool execution result. */ + params: CallToolResultSchema.describe("Standard MCP tool execution result."), +}); + +/** + * @description Rich context about the host environment provided to Guest UIs. + */ +export const McpUiHostContextSchema = z.object({ + /** @description Metadata of the tool call that instantiated this App. */ + toolInfo: z + .object({ + /** @description JSON-RPC id of the tools/call request. */ + id: RequestIdSchema.describe("JSON-RPC id of the tools/call request."), + /** @description Tool definition including name, inputSchema, etc. */ + tool: ToolSchema.describe( + "Tool definition including name, inputSchema, etc.", + ), + }) + .optional() + .describe("Metadata of the tool call that instantiated this App."), + /** @description Current color theme preference. */ + theme: McpUiThemeSchema.optional().describe( + "Current color theme preference.", + ), + /** @description How the UI is currently displayed. */ + displayMode: McpUiDisplayModeSchema.optional().describe( + "How the UI is currently displayed.", + ), + /** @description Display modes the host supports. */ + availableDisplayModes: z + .array(z.string()) + .optional() + .describe("Display modes the host supports."), + /** @description Current and maximum dimensions available to the UI. */ + viewport: z + .object({ + /** @description Current viewport width in pixels. */ + width: z.number().describe("Current viewport width in pixels."), + /** @description Current viewport height in pixels. */ + height: z.number().describe("Current viewport height in pixels."), + /** @description Maximum available height in pixels (if constrained). */ + maxHeight: z + .number() + .optional() + .describe("Maximum available height in pixels (if constrained)."), + /** @description Maximum available width in pixels (if constrained). */ + maxWidth: z + .number() + .optional() + .describe("Maximum available width in pixels (if constrained)."), + }) + .optional() + .describe("Current and maximum dimensions available to the UI."), + /** @description User's language and region preference in BCP 47 format. */ + locale: z + .string() + .optional() + .describe("User's language and region preference in BCP 47 format."), + /** @description User's timezone in IANA format. */ + timeZone: z.string().optional().describe("User's timezone in IANA format."), + /** @description Host application identifier. */ + userAgent: z.string().optional().describe("Host application identifier."), + /** @description Platform type for responsive design decisions. */ + platform: z + .union([z.literal("web"), z.literal("desktop"), z.literal("mobile")]) + .optional() + .describe("Platform type for responsive design decisions."), + /** @description Device input capabilities. */ + deviceCapabilities: z + .object({ + /** @description Whether the device supports touch input. */ + touch: z + .boolean() + .optional() + .describe("Whether the device supports touch input."), + /** @description Whether the device supports hover interactions. */ + hover: z + .boolean() + .optional() + .describe("Whether the device supports hover interactions."), + }) + .optional() + .describe("Device input capabilities."), + /** @description Mobile safe area boundaries in pixels. */ + safeAreaInsets: z + .object({ + /** @description Top safe area inset in pixels. */ + top: z.number().describe("Top safe area inset in pixels."), + /** @description Right safe area inset in pixels. */ + right: z.number().describe("Right safe area inset in pixels."), + /** @description Bottom safe area inset in pixels. */ + bottom: z.number().describe("Bottom safe area inset in pixels."), + /** @description Left safe area inset in pixels. */ + left: z.number().describe("Left safe area inset in pixels."), + }) + .optional() + .describe("Mobile safe area boundaries in pixels."), +}); + +/** + * @description Notification that host context has changed (Host -> Guest UI). + * @see {@link McpUiHostContext} for the full context structure + */ +export const McpUiHostContextChangedNotificationSchema = z.object({ + method: z.literal("ui/notifications/host-context-changed"), + /** @description Partial context update containing only changed fields. */ + params: McpUiHostContextSchema.describe( + "Partial context update containing only changed fields.", + ), +}); + +/** + * @description Initialization request sent from Guest UI to Host. + * @see {@link app.App.connect} for the method that sends this request + */ +export const McpUiInitializeRequestSchema = z.object({ + method: z.literal("ui/initialize"), + params: z.object({ + /** @description App identification (name and version). */ + appInfo: ImplementationSchema.describe( + "App identification (name and version).", + ), + /** @description Features and capabilities this app provides. */ + appCapabilities: McpUiAppCapabilitiesSchema.describe( + "Features and capabilities this app provides.", + ), + /** @description Protocol version this app supports. */ + protocolVersion: z.string().describe("Protocol version this app supports."), + }), +}); + +/** + * @description Initialization result returned from Host to Guest UI. + * @see {@link McpUiInitializeRequest} + */ +export const McpUiInitializeResultSchema = z.looseObject({ + /** @description Negotiated protocol version string (e.g., "2025-11-21"). */ + protocolVersion: z + .string() + .describe('Negotiated protocol version string (e.g., "2025-11-21").'), + /** @description Host application identification and version. */ + hostInfo: ImplementationSchema.describe( + "Host application identification and version.", + ), + /** @description Features and capabilities provided by the host. */ + hostCapabilities: McpUiHostCapabilitiesSchema.describe( + "Features and capabilities provided by the host.", + ), + /** @description Rich context about the host environment. */ + hostContext: McpUiHostContextSchema.describe( + "Rich context about the host environment.", + ), +}); diff --git a/src/spec.types.ts b/src/spec.types.ts new file mode 100644 index 00000000..2596bff5 --- /dev/null +++ b/src/spec.types.ts @@ -0,0 +1,358 @@ +/** + * MCP Apps Protocol Types (spec.types.ts) + * + * This file contains pure TypeScript interface definitions for the MCP Apps protocol. + * These types are the source of truth and are used to generate Zod schemas via ts-to-zod. + * + * - Use `@description` JSDoc tags to generate `.describe()` calls on schemas + * - Run `npm run generate:schemas` to regenerate schemas from these types + * + * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx + */ + +import type { + CallToolResult, + ContentBlock, + Implementation, + RequestId, + Tool, +} from "@modelcontextprotocol/sdk/types.js"; + +/** + * Current protocol version supported by this SDK. + * + * The SDK automatically handles version negotiation during initialization. + * Apps and hosts don't need to manage protocol versions manually. + */ +export const LATEST_PROTOCOL_VERSION = "2025-11-21"; + +/** + * @description Color theme preference for the host environment. + */ +export type McpUiTheme = "light" | "dark"; + +/** + * @description Display mode for UI presentation. + */ +export type McpUiDisplayMode = "inline" | "fullscreen" | "pip"; + +/** + * @description Request to open an external URL in the host's default browser. + * @see {@link app.App.sendOpenLink} for the method that sends this request + */ +export interface McpUiOpenLinkRequest { + method: "ui/open-link"; + params: { + /** @description URL to open in the host's browser */ + url: string; + }; +} + +/** + * @description Result from opening a URL. + * @see {@link McpUiOpenLinkRequest} + */ +export interface McpUiOpenLinkResult { + /** @description True if the host failed to open the URL (e.g., due to security policy). */ + isError?: boolean; + /** + * Index signature required for MCP SDK `Protocol` class compatibility. + * Note: The schema intentionally omits this to enforce strict validation. + */ + [key: string]: unknown; +} + +/** + * @description Request to send a message to the host's chat interface. + * @see {@link app.App.sendMessage} for the method that sends this request + */ +export interface McpUiMessageRequest { + method: "ui/message"; + params: { + /** @description Message role, currently only "user" is supported. */ + role: "user"; + /** @description Message content blocks (text, image, etc.). */ + content: ContentBlock[]; + }; +} + +/** + * @description Result from sending a message. + * @see {@link McpUiMessageRequest} + */ +export interface McpUiMessageResult { + /** @description True if the host rejected or failed to deliver the message. */ + isError?: boolean; + /** + * Index signature required for MCP SDK `Protocol` class compatibility. + * Note: The schema intentionally omits this to enforce strict validation. + */ + [key: string]: unknown; +} + +/** + * @description Notification that the sandbox proxy iframe is ready to receive content. + * @internal + * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy + */ +export interface McpUiSandboxProxyReadyNotification { + method: "ui/notifications/sandbox-proxy-ready"; + params: {}; +} + +/** + * @description Notification containing HTML resource for the sandbox proxy to load. + * @internal + * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy + */ +export interface McpUiSandboxResourceReadyNotification { + method: "ui/notifications/sandbox-resource-ready"; + params: { + /** @description HTML content to load into the inner iframe. */ + html: string; + /** @description Optional override for the inner iframe's sandbox attribute. */ + sandbox?: string; + /** @description CSP configuration from resource metadata. */ + csp?: { + /** @description Origins for network requests (fetch/XHR/WebSocket). */ + connectDomains?: string[]; + /** @description Origins for static resources (scripts, images, styles, fonts). */ + resourceDomains?: string[]; + }; + }; +} + +/** + * @description Notification of UI size changes (bidirectional: Guest <-> Host). + * @see {@link app.App.sendSizeChanged} for the method to send this from Guest UI + */ +export interface McpUiSizeChangedNotification { + method: "ui/notifications/size-changed"; + params: { + /** @description New width in pixels. */ + width?: number; + /** @description New height in pixels. */ + height?: number; + }; +} + +/** + * @description Notification containing complete tool arguments (Host -> Guest UI). + */ +export interface McpUiToolInputNotification { + method: "ui/notifications/tool-input"; + params: { + /** @description Complete tool call arguments as key-value pairs. */ + arguments?: Record; + }; +} + +/** + * @description Notification containing partial/streaming tool arguments (Host -> Guest UI). + */ +export interface McpUiToolInputPartialNotification { + method: "ui/notifications/tool-input-partial"; + params: { + /** @description Partial tool call arguments (incomplete, may change). */ + arguments?: Record; + }; +} + +/** + * @description Notification containing tool execution result (Host -> Guest UI). + */ +export interface McpUiToolResultNotification { + method: "ui/notifications/tool-result"; + /** @description Standard MCP tool execution result. */ + params: CallToolResult; +} + +/** + * @description Rich context about the host environment provided to Guest UIs. + */ +export interface McpUiHostContext { + /** @description Metadata of the tool call that instantiated this App. */ + toolInfo?: { + /** @description JSON-RPC id of the tools/call request. */ + id: RequestId; + /** @description Tool definition including name, inputSchema, etc. */ + tool: Tool; + }; + /** @description Current color theme preference. */ + theme?: McpUiTheme; + /** @description How the UI is currently displayed. */ + displayMode?: McpUiDisplayMode; + /** @description Display modes the host supports. */ + availableDisplayModes?: string[]; + /** @description Current and maximum dimensions available to the UI. */ + viewport?: { + /** @description Current viewport width in pixels. */ + width: number; + /** @description Current viewport height in pixels. */ + height: number; + /** @description Maximum available height in pixels (if constrained). */ + maxHeight?: number; + /** @description Maximum available width in pixels (if constrained). */ + maxWidth?: number; + }; + /** @description User's language and region preference in BCP 47 format. */ + locale?: string; + /** @description User's timezone in IANA format. */ + timeZone?: string; + /** @description Host application identifier. */ + userAgent?: string; + /** @description Platform type for responsive design decisions. */ + platform?: "web" | "desktop" | "mobile"; + /** @description Device input capabilities. */ + deviceCapabilities?: { + /** @description Whether the device supports touch input. */ + touch?: boolean; + /** @description Whether the device supports hover interactions. */ + hover?: boolean; + }; + /** @description Mobile safe area boundaries in pixels. */ + safeAreaInsets?: { + /** @description Top safe area inset in pixels. */ + top: number; + /** @description Right safe area inset in pixels. */ + right: number; + /** @description Bottom safe area inset in pixels. */ + bottom: number; + /** @description Left safe area inset in pixels. */ + left: number; + }; +} + +/** + * @description Notification that host context has changed (Host -> Guest UI). + * @see {@link McpUiHostContext} for the full context structure + */ +export interface McpUiHostContextChangedNotification { + method: "ui/notifications/host-context-changed"; + /** @description Partial context update containing only changed fields. */ + params: McpUiHostContext; +} + +/** + * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). + * @see {@link app-bridge.AppBridge.sendResourceTeardown} for the host method that sends this + */ +export interface McpUiResourceTeardownRequest { + method: "ui/resource-teardown"; + params: {}; +} + +/** + * @description Result from graceful shutdown request. + * @see {@link McpUiResourceTeardownRequest} + */ +export interface McpUiResourceTeardownResult { + /** + * Index signature required for MCP SDK `Protocol` class compatibility. + */ + [key: string]: unknown; +} + +/** + * @description Capabilities supported by the host application. + * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities + */ +export interface McpUiHostCapabilities { + /** @description Experimental features (structure TBD). */ + experimental?: {}; + /** @description Host supports opening external URLs. */ + openLinks?: {}; + /** @description Host can proxy tool calls to the MCP server. */ + serverTools?: { + /** @description Host supports tools/list_changed notifications. */ + listChanged?: boolean; + }; + /** @description Host can proxy resource reads to the MCP server. */ + serverResources?: { + /** @description Host supports resources/list_changed notifications. */ + listChanged?: boolean; + }; + /** @description Host accepts log messages. */ + logging?: {}; +} + +/** + * @description Capabilities provided by the Guest UI (App). + * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities + */ +export interface McpUiAppCapabilities { + /** @description Experimental features (structure TBD). */ + experimental?: {}; + /** @description App exposes MCP-style tools that the host can call. */ + tools?: { + /** @description App supports tools/list_changed notifications. */ + listChanged?: boolean; + }; +} + +/** + * @description Initialization request sent from Guest UI to Host. + * @see {@link app.App.connect} for the method that sends this request + */ +export interface McpUiInitializeRequest { + method: "ui/initialize"; + params: { + /** @description App identification (name and version). */ + appInfo: Implementation; + /** @description Features and capabilities this app provides. */ + appCapabilities: McpUiAppCapabilities; + /** @description Protocol version this app supports. */ + protocolVersion: string; + }; +} + +/** + * @description Initialization result returned from Host to Guest UI. + * @see {@link McpUiInitializeRequest} + */ +export interface McpUiInitializeResult { + /** @description Negotiated protocol version string (e.g., "2025-11-21"). */ + protocolVersion: string; + /** @description Host application identification and version. */ + hostInfo: Implementation; + /** @description Features and capabilities provided by the host. */ + hostCapabilities: McpUiHostCapabilities; + /** @description Rich context about the host environment. */ + hostContext: McpUiHostContext; + /** + * Index signature required for MCP SDK `Protocol` class compatibility. + * Note: The schema intentionally omits this to enforce strict validation. + */ + [key: string]: unknown; +} + +/** + * @description Notification that Guest UI has completed initialization (Guest UI -> Host). + * @see {@link app.App.connect} for the method that sends this notification + */ +export interface McpUiInitializedNotification { + method: "ui/notifications/initialized"; + params?: {}; +} + +/** + * @description Content Security Policy configuration for UI resources. + */ +export interface McpUiResourceCsp { + /** @description Origins for network requests (fetch/XHR/WebSocket). */ + connectDomains?: string[]; + /** @description Origins for static resources (scripts, images, styles, fonts). */ + resourceDomains?: string[]; +} + +/** + * @description UI Resource metadata for security and rendering configuration. + */ +export interface McpUiResourceMeta { + /** @description Content Security Policy configuration. */ + csp?: McpUiResourceCsp; + /** @description Dedicated origin for widget sandbox. */ + domain?: string; + /** @description Visual boundary preference - true if UI prefers a visible border. */ + prefersBorder?: boolean; +} diff --git a/src/types.ts b/src/types.ts index e08d2366..92bb8cf8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,895 +1,65 @@ -import { - CallToolResult, - CallToolResultSchema, - ContentBlock, - ContentBlockSchema, - EmptyResultSchema, - Implementation, - ImplementationSchema, - RequestId, - RequestIdSchema, - RequestSchema, - Tool, - ToolSchema, -} from "@modelcontextprotocol/sdk/types.js"; -import { z } from "zod/v4"; - -/** - * Type-level assertion that validates a Zod schema produces the expected interface. - * - * This helper is used for request and notification schemas that cannot use - * `z.ZodType` type annotations. Adding `: z.ZodType` to - * schemas widens the type from the specific `ZodObject` to the generic `ZodType`, - * which breaks MCP SDK's `setRequestHandler()` and `setNotificationHandler()` - * methods that require the specific `ZodObject` type. - * - * By using this type-level assertion instead, we get compile-time validation that - * the schema matches the interface without affecting the runtime schema type. - * - * @internal - */ -type VerifySchemaMatches = - z.infer extends TInterface - ? TInterface extends z.infer - ? true - : never - : never; - -/** - * Current protocol version supported by this SDK. - * - * The SDK automatically handles version negotiation during initialization. - * Apps and hosts don't need to manage protocol versions manually. - */ -export const LATEST_PROTOCOL_VERSION = "2025-11-21"; - -/** - * Color theme preference for the host environment. - * @see {@link McpUiHostContext.theme} - */ -export type McpUiTheme = "light" | "dark"; - -/** Runtime validation schema for {@link McpUiTheme}. */ -export const McpUiThemeSchema = z.enum(["light", "dark"]); - -/** - * Display mode for UI presentation. - * - `inline`: Embedded within the conversation flow - * - `fullscreen`: Expanded to fill the available viewport - * - `pip`: Picture-in-picture floating window - * - * @see {@link McpUiHostContext.displayMode} - */ -export type McpUiDisplayMode = "inline" | "fullscreen" | "pip"; - -/** Runtime validation schema for {@link McpUiDisplayMode}. */ -export const McpUiDisplayModeSchema = z.enum(["inline", "fullscreen", "pip"]); - -/** - * Request to open an external URL in the host's default browser. - * - * Sent from the Guest UI to the Host when requesting to open an external link. - * The host may deny the request based on user preferences or security policy. - * - * @see {@link app.App.sendOpenLink} for the method that sends this request - */ -export interface McpUiOpenLinkRequest { - method: "ui/open-link"; - params: { - /** URL to open in the host's browser */ - url: string; - }; -} - -/** - * Runtime validation schema for {@link McpUiOpenLinkRequest}. - * @internal - */ -export const McpUiOpenLinkRequestSchema = RequestSchema.extend({ - method: z.literal("ui/open-link"), - params: z.object({ - url: z.string().url(), - }), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyOpenLinkRequest = VerifySchemaMatches< - typeof McpUiOpenLinkRequestSchema, - McpUiOpenLinkRequest ->; - -/** - * Result from a {@link McpUiOpenLinkRequest}. - * - * The host returns this result after attempting to open the requested URL. - * - * @see {@link McpUiOpenLinkRequest} - */ -export interface McpUiOpenLinkResult { - /** - * True if the host failed to open the URL (e.g., due to security policy, - * user cancellation, or system error). False or undefined indicates success. - */ - isError?: boolean; - /** - * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. - */ - [key: string]: unknown; -} - -/** - * Runtime validation schema for {@link McpUiOpenLinkResult}. - * @internal - */ -export const McpUiOpenLinkResultSchema: z.ZodType = - z.object({ - isError: z.boolean().optional(), - }); - -/** - * Request to send a message to the host's chat interface. - * - * Sent from the Guest UI to the Host when the app wants to add a message to the - * conversation thread. This enables interactive apps to communicate with the user - * through the host's chat interface. - * - * @see {@link app.App.sendMessage} for the method that sends this request - */ -export interface McpUiMessageRequest { - method: "ui/message"; - params: { - /** Message role, currently only "user" is supported */ - role: "user"; - /** Message content blocks (text, image, etc.) */ - content: ContentBlock[]; - }; -} - -/** - * Runtime validation schema for {@link McpUiMessageRequest}. - * @internal - */ -export const McpUiMessageRequestSchema = RequestSchema.extend({ - method: z.literal("ui/message"), - params: z.object({ - role: z.literal("user"), - content: z.array(ContentBlockSchema), - }), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyMessageRequest = VerifySchemaMatches< - typeof McpUiMessageRequestSchema, - McpUiMessageRequest ->; - -/** - * Result from a {@link McpUiMessageRequest}. - * - * Note: The host does not return message content or follow-up results to prevent - * leaking information from the conversation. Only error status is provided. - * - * @see {@link McpUiMessageRequest} - */ -export interface McpUiMessageResult { - /** - * True if the host rejected or failed to deliver the message (e.g., due to - * rate limiting, content policy, or system error). False or undefined - * indicates the message was accepted. - */ - isError?: boolean; - /** - * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. - */ - [key: string]: unknown; -} - /** - * Runtime validation schema for {@link McpUiMessageResult}. - * @internal - */ -export const McpUiMessageResultSchema: z.ZodType = z.object( - { - isError: z.boolean().optional(), - }, -); - -// McpUiIframeReadyNotification removed - replaced by standard MCP initialization -// The SDK's oninitialized callback now handles the ready signal - -/** - * Notification that the sandbox proxy iframe is ready to receive content. - * - * This is an internal message used by web-based hosts implementing the - * double-iframe sandbox architecture. The sandbox proxy sends this to the host - * after it loads and is ready to receive HTML content via - * {@link McpUiSandboxResourceReadyNotification}. - * - * @internal - * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy - */ -export interface McpUiSandboxProxyReadyNotification { - method: "ui/notifications/sandbox-proxy-ready"; - params: {}; -} - -/** - * Runtime validation schema for {@link McpUiSandboxProxyReadyNotification}. - * @internal - */ -export const McpUiSandboxProxyReadyNotificationSchema = z.object({ - method: z.literal("ui/notifications/sandbox-proxy-ready"), - params: z.object({}), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifySandboxProxyReadyNotification = VerifySchemaMatches< - typeof McpUiSandboxProxyReadyNotificationSchema, - McpUiSandboxProxyReadyNotification ->; - -/** - * Notification containing HTML resource for the sandbox proxy to load. - * - * This is an internal message used by web-based hosts implementing the - * double-iframe sandbox architecture. After the sandbox proxy signals readiness, - * the host sends this notification with the HTML content and optional sandbox - * attributes to load into the inner iframe. - * - * @internal - * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy - */ -export interface McpUiSandboxResourceReadyNotification { - method: "ui/notifications/sandbox-resource-ready"; - params: { - /** HTML content to load into the inner iframe */ - html: string; - /** Optional override for the inner iframe's sandbox attribute */ - sandbox?: string; - /** CSP configuration from resource metadata */ - csp?: { - /** Origins for network requests (fetch/XHR/WebSocket) */ - connectDomains?: string[]; - /** Origins for static resources (scripts, images, styles, fonts) */ - resourceDomains?: string[]; - }; - }; -} - -/** - * Runtime validation schema for {@link McpUiSandboxResourceReadyNotification}. - * @internal - */ -export const McpUiSandboxResourceReadyNotificationSchema = z.object({ - method: z.literal("ui/notifications/sandbox-resource-ready"), - params: z.object({ - html: z.string(), - sandbox: z.string().optional(), - csp: z - .object({ - connectDomains: z.array(z.string()).optional(), - resourceDomains: z.array(z.string()).optional(), - }) - .optional(), - }), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifySandboxResourceReadyNotification = VerifySchemaMatches< - typeof McpUiSandboxResourceReadyNotificationSchema, - McpUiSandboxResourceReadyNotification ->; - -/** - * Notification of UI size changes (bidirectional: Guest ↔ Host). - * - * **Guest UI → Host**: Sent by the Guest UI when its rendered content size changes, - * typically using ResizeObserver. This helps the host adjust the iframe container. - * If {@link app.App} is configured with `autoResize: true` (default), this is sent - * automatically. - * - * **Host → Guest UI**: Sent by the Host when the viewport size changes (e.g., - * window resize, orientation change). This allows the Guest UI to adjust its layout. - * - * @see {@link app.App.sendSizeChanged} for the method to send this from Guest UI - * @see {@link app.App.setupSizeChangedNotifications} for automatic size reporting - */ -export interface McpUiSizeChangedNotification { - method: "ui/notifications/size-changed"; - params: { - /** New width in pixels */ - width?: number; - /** New height in pixels */ - height?: number; - }; -} - -/** - * Runtime validation schema for {@link McpUiSizeChangedNotification}. - * @internal - */ -export const McpUiSizeChangedNotificationSchema = z.object({ - method: z.literal("ui/notifications/size-changed"), - params: z.object({ - width: z.number().optional(), - height: z.number().optional(), - }), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifySizeChangeNotification = VerifySchemaMatches< - typeof McpUiSizeChangedNotificationSchema, - McpUiSizeChangedNotification ->; - -/** - * Notification containing complete tool arguments (Host → Guest UI). - * - * The host MUST send this notification after the Guest UI's initialize request - * completes, when complete tool arguments become available. This notification is - * sent exactly once and is required before {@link McpUiToolResultNotification}. - * - * The arguments object contains the complete tool call parameters that triggered - * this App instance. - */ -export interface McpUiToolInputNotification { - method: "ui/notifications/tool-input"; - params: { - /** Complete tool call arguments as key-value pairs */ - arguments?: Record; - }; -} - -/** - * Runtime validation schema for {@link McpUiToolInputNotification}. - * @internal - */ -export const McpUiToolInputNotificationSchema = z.object({ - method: z.literal("ui/notifications/tool-input"), - params: z.object({ - arguments: z.record(z.string(), z.unknown()).optional(), - }), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyToolInputNotification = VerifySchemaMatches< - typeof McpUiToolInputNotificationSchema, - McpUiToolInputNotification ->; - -/** - * Notification containing partial/streaming tool arguments (Host → Guest UI). - * - * The host MAY send this notification zero or more times while the agent is - * streaming tool arguments, before {@link McpUiToolInputNotification} is sent - * with complete arguments. - * - * The arguments object represents best-effort recovery of incomplete JSON, with - * unclosed structures automatically closed to produce valid JSON. Guest UIs may - * ignore these notifications or use them to render progressive loading states. - * - * Guest UIs MUST NOT rely on partial arguments for critical operations and SHOULD - * gracefully handle missing or changing fields between notifications. - */ -export interface McpUiToolInputPartialNotification { - method: "ui/notifications/tool-input-partial"; - params: { - /** Partial tool call arguments (incomplete, may change) */ - arguments?: Record; - }; -} - -/** - * Runtime validation schema for {@link McpUiToolInputPartialNotification}. - * @internal - */ -export const McpUiToolInputPartialNotificationSchema = z.object({ - method: z.literal("ui/notifications/tool-input-partial"), - params: z.object({ - arguments: z.record(z.string(), z.unknown()).optional(), - }), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyToolInputPartialNotification = VerifySchemaMatches< - typeof McpUiToolInputPartialNotificationSchema, - McpUiToolInputPartialNotification ->; - -/** - * Notification containing tool execution result (Host → Guest UI). - * - * The host MUST send this notification when tool execution completes successfully, - * provided the UI is still displayed. If the UI was closed before execution - * completes, the host MAY skip this notification. This notification is sent after - * {@link McpUiToolInputNotification}. - * - * The result follows the standard MCP CallToolResult format, containing content - * for the model and optionally structuredContent optimized for UI rendering. - */ -export interface McpUiToolResultNotification { - method: "ui/notifications/tool-result"; - /** Standard MCP tool execution result */ - params: CallToolResult; -} - -/** - * Runtime validation schema for {@link McpUiToolResultNotification}. - * @internal - */ -export const McpUiToolResultNotificationSchema = z.object({ - method: z.literal("ui/notifications/tool-result"), - params: CallToolResultSchema, -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyToolResultNotification = VerifySchemaMatches< - typeof McpUiToolResultNotificationSchema, - McpUiToolResultNotification ->; - -/** - * Rich context about the host environment provided to Guest UIs. - * - * Hosts provide this context in the {@link McpUiInitializeResult} response and send - * updates via {@link McpUiHostContextChangedNotification} when values change. - * All fields are optional and Guest UIs should handle missing fields gracefully. - * - * @example - * ```typescript - * // Received during initialization - * const result = await app.connect(transport); - * const context = result.hostContext; - * - * if (context.theme === "dark") { - * document.body.classList.add("dark-mode"); - * } - * ``` - */ -export interface McpUiHostContext { - /** Metadata of the tool call that instantiated this App */ - toolInfo?: { - /** JSON-RPC id of the tools/call request */ - id: RequestId; - /** Tool definition including name, inputSchema, etc. */ - tool: Tool; - }; - /** - * Current color theme preference. - * @example "dark" - */ - theme?: McpUiTheme; - /** - * How the UI is currently displayed. - * @example "inline" - */ - displayMode?: McpUiDisplayMode; - /** - * Display modes the host supports. - * Apps can use this to offer mode-switching UI if applicable. - */ - availableDisplayModes?: string[]; - /** Current and maximum dimensions available to the UI */ - viewport?: { - /** Current viewport width in pixels */ - width: number; - /** Current viewport height in pixels */ - height: number; - /** Maximum available height in pixels (if constrained) */ - maxHeight?: number; - /** Maximum available width in pixels (if constrained) */ - maxWidth?: number; - }; - /** - * User's language and region preference in BCP 47 format. - * @example "en-US", "fr-CA", "ja-JP" - */ - locale?: string; - /** - * User's timezone in IANA format. - * @example "America/New_York", "Europe/London", "Asia/Tokyo" - */ - timeZone?: string; - /** - * Host application identifier. - * @example "claude-desktop/1.0.0" - */ - userAgent?: string; - /** - * Platform type for responsive design decisions. - * @example "desktop" - */ - platform?: "web" | "desktop" | "mobile"; - /** Device input capabilities */ - deviceCapabilities?: { - /** Whether the device supports touch input */ - touch?: boolean; - /** Whether the device supports hover interactions */ - hover?: boolean; - }; - /** - * Safe area boundaries in pixels. - * Used to avoid notches, rounded corners, and system UI. - */ - safeAreaInsets?: { - /** Top safe area inset in pixels */ - top: number; - /** Right safe area inset in pixels */ - right: number; - /** Bottom safe area inset in pixels */ - bottom: number; - /** Left safe area inset in pixels */ - left: number; - }; -} - -/** - * Runtime validation schema for {@link McpUiHostContext}. - * @internal - */ -export const McpUiHostContextSchema: z.ZodType = z.object({ - toolInfo: z - .object({ - id: RequestIdSchema, - tool: ToolSchema, - }) - .optional(), - theme: McpUiThemeSchema.optional(), - displayMode: McpUiDisplayModeSchema.optional(), - availableDisplayModes: z.array(z.string()).optional(), - viewport: z - .object({ - width: z.number(), - height: z.number(), - maxHeight: z.number().optional(), - maxWidth: z.number().optional(), - }) - .optional(), - locale: z.string().optional(), - timeZone: z.string().optional(), - userAgent: z.string().optional(), - platform: z.enum(["web", "desktop", "mobile"]).optional(), - deviceCapabilities: z - .object({ - touch: z.boolean().optional(), - hover: z.boolean().optional(), - }) - .optional(), - safeAreaInsets: z - .object({ - top: z.number(), - right: z.number(), - bottom: z.number(), - left: z.number(), - }) - .optional(), -}); - -/** - * Notification that host context has changed (Host → Guest UI). - * - * The host MAY send this notification when any context field changes, such as: - * - Theme toggled (light/dark) - * - Display mode changed (inline/fullscreen) - * - Device orientation changed - * - Window/panel resized - * - * This notification contains partial updates. Guest UIs SHOULD merge received - * fields with their current context state rather than replacing it entirely. - * - * @see {@link McpUiHostContext} for the full context structure - */ -export interface McpUiHostContextChangedNotification { - method: "ui/notifications/host-context-changed"; - /** Partial context update containing only changed fields */ - params: McpUiHostContext; -} - -/** - * Runtime validation schema for {@link McpUiHostContextChangedNotification}. - * @internal - */ -export const McpUiHostContextChangedNotificationSchema = z.object({ - method: z.literal("ui/notifications/host-context-changed"), - params: McpUiHostContextSchema, -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyHostContextChangedNotification = VerifySchemaMatches< - typeof McpUiHostContextChangedNotificationSchema, - McpUiHostContextChangedNotification ->; - -/** - * Request for graceful shutdown of the Guest UI (Host → Guest UI). - * - * The host MUST send this request before tearing down the UI resource, for any - * reason including user action, resource reallocation, or app closure. This gives - * the Guest UI an opportunity to save state, cancel pending operations, or show - * confirmation dialogs. - * - * The host SHOULD wait for the response before unmounting the iframe to prevent - * data loss. - * - * @see {@link app-bridge.AppBridge.sendResourceTeardown} for the host method that sends this - */ -export interface McpUiResourceTeardownRequest { - method: "ui/resource-teardown"; - params: {}; -} - -/** - * Runtime validation schema for {@link McpUiResourceTeardownRequest}. - * @internal - */ -export const McpUiResourceTeardownRequestSchema = RequestSchema.extend({ - method: z.literal("ui/resource-teardown"), - params: z.object({}), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyResourceTeardownRequest = VerifySchemaMatches< - typeof McpUiResourceTeardownRequestSchema, - McpUiResourceTeardownRequest ->; - -/** - * Result from graceful shutdown request. - * - * Empty result indicates the Guest UI has completed cleanup and is ready to be - * torn down. - * - * @see {@link McpUiResourceTeardownRequest} - */ -export interface McpUiResourceTeardownResult {} - -/** - * Runtime validation schema for {@link McpUiResourceTeardownResult}. - * @internal - */ -export const McpUiResourceTeardownResultSchema: z.ZodType = - EmptyResultSchema; - -/** - * Capabilities supported by the host application. - * - * Hosts declare these capabilities during the initialization handshake. Guest UIs - * can check capabilities before attempting to use specific features. - * - * @example Check if host supports opening links - * ```typescript - * const result = await app.connect(transport); - * if (result.hostCapabilities.openLinks) { - * await app.sendOpenLink({ url: "https://example.com" }); - * } - * ``` - * - * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities - */ -export interface McpUiHostCapabilities { - /** Experimental features (structure TBD) */ - experimental?: {}; - /** Host supports opening external URLs via {@link app.App.sendOpenLink} */ - openLinks?: {}; - /** Host can proxy tool calls to the MCP server */ - serverTools?: { - /** Host supports tools/list_changed notifications */ - listChanged?: boolean; - }; - /** Host can proxy resource reads to the MCP server */ - serverResources?: { - /** Host supports resources/list_changed notifications */ - listChanged?: boolean; - }; - /** Host accepts log messages via {@link app.App.sendLog} */ - logging?: {}; -} - -/** - * Runtime validation schema for {@link McpUiHostCapabilities}. - * @internal - */ -export const McpUiHostCapabilitiesSchema: z.ZodType = - z.object({ - experimental: z.object({}).optional(), - openLinks: z.object({}).optional(), - serverTools: z - .object({ - listChanged: z.boolean().optional(), - }) - .optional(), - serverResources: z - .object({ - listChanged: z.boolean().optional(), - }) - .optional(), - logging: z.object({}).optional(), - }); - -/** - * Capabilities provided by the Guest UI (App). - * - * Apps declare these capabilities during the initialization handshake to indicate - * what features they provide to the host. - * - * @example Declare tool capabilities - * ```typescript - * const app = new App( - * { name: "MyApp", version: "1.0.0" }, - * { tools: { listChanged: true } } - * ); - * ``` - * - * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities - */ -export interface McpUiAppCapabilities { - /** Experimental features (structure TBD) */ - experimental?: {}; - /** - * App exposes MCP-style tools that the host can call. - * These are app-specific tools, not proxied from the server. - */ - tools?: { - /** App supports tools/list_changed notifications */ - listChanged?: boolean; - }; -} - -/** - * Runtime validation schema for {@link McpUiAppCapabilities}. - * @internal - */ -export const McpUiAppCapabilitiesSchema: z.ZodType = - z.object({ - experimental: z.object({}).optional(), - tools: z - .object({ - listChanged: z.boolean().optional(), - }) - .optional(), - }); - -/** - * Initialization request sent from Guest UI to Host. - * - * This is the first message sent by the Guest UI after loading. The host responds - * with {@link McpUiInitializeResult} containing host capabilities and context. - * After receiving the response, the Guest UI MUST send - * {@link McpUiInitializedNotification}. - * - * This replaces the custom iframe-ready pattern used in pre-SEP MCP-UI. - * - * @see {@link app.App.connect} for the method that sends this request - */ -export interface McpUiInitializeRequest { - method: "ui/initialize"; - params: { - /** App identification (name and version) */ - appInfo: Implementation; - /** Features and capabilities this app provides */ - appCapabilities: McpUiAppCapabilities; - /** Protocol version this app supports */ - protocolVersion: string; - }; -} - -/** - * Runtime validation schema for {@link McpUiInitializeRequest}. - * @internal - */ -export const McpUiInitializeRequestSchema = RequestSchema.extend({ - method: z.literal("ui/initialize"), - params: z.object({ - appInfo: ImplementationSchema, - appCapabilities: McpUiAppCapabilitiesSchema, - protocolVersion: z.string(), - }), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyInitializeRequest = VerifySchemaMatches< - typeof McpUiInitializeRequestSchema, - McpUiInitializeRequest ->; - -/** - * Initialization result returned from Host to Guest UI. - * - * Contains the negotiated protocol version, host information, capabilities, - * and rich context about the host environment. - * - * @see {@link McpUiInitializeRequest} - */ -export interface McpUiInitializeResult { - /** Negotiated protocol version string (e.g., "2025-11-21") */ - protocolVersion: string; - /** Host application identification and version */ - hostInfo: Implementation; - /** Features and capabilities provided by the host */ - hostCapabilities: McpUiHostCapabilities; - /** Rich context about the host environment */ - hostContext: McpUiHostContext; - /** - * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. - */ - [key: string]: unknown; -} - -/** - * Runtime validation schema for {@link McpUiInitializeResult}. - * @internal - */ -export const McpUiInitializeResultSchema: z.ZodType = - z.object({ - protocolVersion: z.string(), - hostInfo: ImplementationSchema, - hostCapabilities: McpUiHostCapabilitiesSchema, - hostContext: McpUiHostContextSchema, - }); - -/** - * Notification that Guest UI has completed initialization (Guest UI → Host). - * - * The Guest UI MUST send this notification after receiving - * {@link McpUiInitializeResult} and completing any setup. The host waits for this - * notification before sending tool input and other data to the Guest UI. - * - * @see {@link app.App.connect} for the method that sends this notification - */ -export interface McpUiInitializedNotification { - method: "ui/notifications/initialized"; - params?: {}; -} - -/** - * Runtime validation schema for {@link McpUiInitializedNotification}. - * @internal - */ -export const McpUiInitializedNotificationSchema = z.object({ - method: z.literal("ui/notifications/initialized"), - params: z.object({}).optional(), -}); - -/** @internal - Compile-time verification that schema matches interface */ -type _VerifyInitializedNotification = VerifySchemaMatches< - typeof McpUiInitializedNotificationSchema, - McpUiInitializedNotification ->; - -// ============================================================================= -// UI Resource Metadata Types -// ============================================================================= - -/** - * Content Security Policy configuration for UI resources. - * - * Servers declare which external origins their UI needs to access. - * Hosts use this to enforce appropriate CSP headers. - */ -export const McpUiResourceCspSchema = z.object({ - /** Origins for network requests (fetch/XHR/WebSocket). Maps to CSP connect-src */ - connectDomains: z.array(z.string()).optional(), - /** Origins for static resources (images, scripts, stylesheets, fonts, media). Maps to CSP img-src, script-src, style-src, font-src, media-src */ - resourceDomains: z.array(z.string()).optional(), -}); -export type McpUiResourceCsp = z.infer; - -/** - * UI Resource metadata for security and rendering configuration. - * - * Included in the `_meta.ui` field of UI resource content returned via `resources/read`. - * - * @see {@link McpUiResourceCspSchema} for CSP configuration - */ -export const McpUiResourceMetaSchema = z.object({ - /** Content Security Policy configuration */ - csp: McpUiResourceCspSchema.optional(), - /** Dedicated origin for widget sandbox */ - domain: z.string().optional(), - /** Visual boundary preference - true if UI prefers a visible border */ - prefersBorder: z.boolean().optional(), -}); -export type McpUiResourceMeta = z.infer; + * MCP Apps Protocol Types and Schemas + * + * This file re-exports types from spec.types.ts and schemas from generated/schema.ts. + * Compile-time verification is handled by generated/schema.test.ts. + * + * @see spec.types.ts for the source of truth TypeScript interfaces + * @see generated/schema.ts for auto-generated Zod schemas + * @see generated/schema.test.ts for compile-time verification + */ + +// Re-export all types from spec.types.ts +export { + LATEST_PROTOCOL_VERSION, + type McpUiTheme, + type McpUiDisplayMode, + type McpUiOpenLinkRequest, + type McpUiOpenLinkResult, + type McpUiMessageRequest, + type McpUiMessageResult, + type McpUiSandboxProxyReadyNotification, + type McpUiSandboxResourceReadyNotification, + type McpUiSizeChangedNotification, + type McpUiToolInputNotification, + type McpUiToolInputPartialNotification, + type McpUiToolResultNotification, + type McpUiHostContext, + type McpUiHostContextChangedNotification, + type McpUiResourceTeardownRequest, + type McpUiResourceTeardownResult, + type McpUiHostCapabilities, + type McpUiAppCapabilities, + type McpUiInitializeRequest, + type McpUiInitializeResult, + type McpUiInitializedNotification, + type McpUiResourceCsp, + type McpUiResourceMeta, +} from "./spec.types.js"; + +// Re-export all schemas from generated/schema.ts (already PascalCase) +export { + McpUiThemeSchema, + McpUiDisplayModeSchema, + McpUiOpenLinkRequestSchema, + McpUiOpenLinkResultSchema, + McpUiMessageRequestSchema, + McpUiMessageResultSchema, + McpUiSandboxProxyReadyNotificationSchema, + McpUiSandboxResourceReadyNotificationSchema, + McpUiSizeChangedNotificationSchema, + McpUiToolInputNotificationSchema, + McpUiToolInputPartialNotificationSchema, + McpUiToolResultNotificationSchema, + McpUiHostContextSchema, + McpUiHostContextChangedNotificationSchema, + McpUiResourceTeardownRequestSchema, + McpUiResourceTeardownResultSchema, + McpUiHostCapabilitiesSchema, + McpUiAppCapabilitiesSchema, + McpUiInitializeRequestSchema, + McpUiInitializeResultSchema, + McpUiInitializedNotificationSchema, + McpUiResourceCspSchema, + McpUiResourceMetaSchema, +} from "./generated/schema.js";