refactor(dashboard): migrate to zod 4 and openai 6 (#44345)

* refactor(dashboard): migrate to zod 4 and openai 6

Bump the dashboard to real zod 4.6.5 and openai 6.49.0 so every module
imports from bare "zod" instead of "zod/v4". Ports the ten files that
still used the zod 3 API (error params, record, passthrough, strict,
email/date validators, union discriminator codes) and adapts the
LiteAdmin tool schemas and form plumbing where openai 6 and zod 4
changed behaviour.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* style(dashboard): prettier format zod 4 schema files

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(dashboard): restore system one missing state message under zod 4

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

Backport notes for stable 1.104.x. package.json and package-lock.json were restored from the line and only openai moves to 6.49.0, since zod is already on 4.6.6 here. The lock change is openai plus the 21 packages only openai 4 needed

agent_identity.ts and the systemOneUI schemas.ts and validatePayload.test.ts do not exist on this line, so their hunks are dropped
build_auto_router_routing_test_request.ts keeps the line's jev-only schema with the record key and loose() from this change, and its default({}) becomes prefault({}) so the saved JEV config defaults are still parsed in under zod 4
jev_classifier_config.ts keeps the line's plain object schema, because the provider transform and refine this change edits are not on this line

---------

Co-authored-by: Yujong Lee <yujong@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 0c86d6bfc9)
This commit is contained in:
devin-ai-integration[bot] 2026-10-03 06:53:41 +00:00 • committed by Yuneng Jiang
parent bee14f41e9
commit 285d52bb63
No known key found for this signature in database
70 changed files with 182 additions and 365 deletions

View file

@ -58,6 +58,10 @@ const eslintConfig = [
message:
"@tremor/react is being phased out; build new UI with shadcn/ui primitives instead of adding tremor imports.",
},
{
group: ["zod/*"],
message: 'Import Zod from "zod"; the dashboard uses Zod 4 only.',
},
],
},
],

View file

@ -28,7 +28,7 @@
"next": "16.4.1",
"next-themes": "^0.4.6",
"nuqs": "^2.9.4",
"openai": "4.104.0",
"openai": "6.49.0",
"openapi-fetch": "^0.17.0",
"openapi-react-query": "^0.5.4",
"papaparse": "5.5.3",
@ -3780,16 +3780,6 @@
"undici-types": "~6.21.0"
}
},
"node_modules/@types/node-fetch": {
"version": "2.6.13",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
"integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
"license": "MIT",
"dependencies": {
"@types/node": "*",
"form-data": "^4.0.4"
}
},
"node_modules/@types/papaparse": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz",
@ -4547,18 +4537,6 @@
"url": "https://opencollective.com/vitest"
}
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"license": "MIT",
"dependencies": {
"event-target-shim": "^5.0.0"
},
"engines": {
"node": ">=6.5"
}
},
"node_modules/acorn": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
@ -4592,18 +4570,6 @@
"node": ">= 14"
}
},
"node_modules/agentkeepalive": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
"integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
"license": "MIT",
"dependencies": {
"humanize-ms": "^1.2.1"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/ajv": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
@ -4880,12 +4846,6 @@
"node": ">= 0.4"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@ -5047,6 +5007,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@ -5241,18 +5202,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/comma-separated-tokens": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
@ -5645,15 +5594,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@ -5710,6 +5650,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
@ -5834,6 +5775,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -5843,6 +5785,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -5887,6 +5830,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@ -5899,6 +5843,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@ -6545,15 +6490,6 @@
"node": ">=0.10.0"
}
},
"node_modules/event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/eventemitter3": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
@ -6765,28 +6701,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/form-data": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.4",
"mime-types": "^2.1.35"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/form-data-encoder": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
"license": "MIT"
},
"node_modules/format": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
@ -6811,19 +6725,6 @@
"node": ">=18.3.0"
}
},
"node_modules/formdata-node": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
"integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
"license": "MIT",
"dependencies": {
"node-domexception": "1.0.0",
"web-streams-polyfill": "4.0.0-beta.3"
},
"engines": {
"node": ">= 12.20"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@ -6843,6 +6744,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@ -6903,6 +6805,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@ -6927,6 +6830,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
@ -7014,6 +6918,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -7085,6 +6990,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -7097,6 +7003,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
@ -7112,6 +7019,7 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@ -7325,15 +7233,6 @@
"node": ">= 14"
}
},
"node_modules/humanize-ms": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
"integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.0.0"
}
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@ -8674,6 +8573,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -9568,27 +9468,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/min-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
@ -9764,26 +9643,6 @@
"react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
}
},
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"deprecated": "Use your platform's native DOMException instead",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"license": "MIT",
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-exports-info": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz",
@ -9813,48 +9672,6 @@
"semver": "bin/semver.js"
}
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/node-releases": {
"version": "2.0.54",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.54.tgz",
@ -10039,27 +9856,27 @@
}
},
"node_modules/openai": {
"version": "4.104.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz",
"integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==",
"version": "6.49.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-6.49.0.tgz",
"integrity": "sha512-aYCc0C6L864eR6WSYIwQGyXriw/nIyZx0ObvhzOEVuk0zoBDpynjSbrionWI7q65B5H8jJX0DXR9snEzM6bfPg==",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "^18.11.18",
"@types/node-fetch": "^2.6.4",
"abort-controller": "^3.0.0",
"agentkeepalive": "^4.2.1",
"form-data-encoder": "1.7.2",
"formdata-node": "^4.3.2",
"node-fetch": "^2.6.7"
},
"bin": {
"openai": "bin/cli"
},
"peerDependencies": {
"@aws-sdk/credential-provider-node": ">=3.972.0 <4",
"@smithy/hash-node": ">=4.3.0 <5",
"@smithy/signature-v4": ">=5.4.0 <6",
"ws": "^8.18.0",
"zod": "^3.23.8"
"zod": "^3.25 || ^4.0"
},
"peerDependenciesMeta": {
"@aws-sdk/credential-provider-node": {
"optional": true
},
"@smithy/hash-node": {
"optional": true
},
"@smithy/signature-v4": {
"optional": true
},
"ws": {
"optional": true
},
@ -10068,21 +9885,6 @@
}
}
},
"node_modules/openai/node_modules/@types/node": {
"version": "18.19.130",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
"integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/openai/node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"license": "MIT"
},
"node_modules/openapi-fetch": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.17.0.tgz",
@ -12565,15 +12367,6 @@
"node": "20 || >=22"
}
},
"node_modules/web-streams-polyfill": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/webidl-conversions": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",

View file

@ -44,7 +44,7 @@
"next": "16.4.1",
"next-themes": "^0.4.6",
"nuqs": "^2.9.4",
"openai": "4.104.0",
"openai": "6.49.0",
"openapi-fetch": "^0.17.0",
"openapi-react-query": "^0.5.4",
"papaparse": "5.5.3",

View file

@ -2,7 +2,7 @@
import { BotIcon, InfoIcon, LayersIcon, ServerIcon } from "lucide-react";
import type { UseFormReturn } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { useAgents } from "@/app/(dashboard)/hooks/agents/useAgents";
import { useMCPServers } from "@/app/(dashboard)/hooks/mcpServers/useMCPServers";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
export const accessGroupCreateSchema = z.object({
name: z.string().refine((value) => value.trim() !== "", "Please enter the access group name"),

View file

@ -30,7 +30,7 @@ import {
type SSOSettingsFormValues,
} from "@/components/Settings/AdminSettings/SSOSettings/Modals/BaseSSOSettingsForm";
import UIAccessControlForm from "@/components/UIAccessControlForm";
import { z } from "zod/v4";
import { z } from "zod";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";
import { Input } from "@/components/ui/input";

View file

@ -1,6 +1,6 @@
import { ChevronRight } from "lucide-react";
import React from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { useCreateBudget } from "@/app/(dashboard)/hooks/budgets/useBudgets";
import { applyBudgetPrecision } from "./budgetPrecision";
import { toast } from "@/lib/toast";

View file

@ -2,7 +2,7 @@
import React, { useState } from "react";
import { CircleAlert } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { Alert, AlertTitle } from "@/components/shared/Alert";
import { PasswordInput } from "@/components/shared/PasswordInput";

View file

@ -2,7 +2,7 @@
import React, { useCallback, useEffect, useState } from "react";
import { CircleHelp } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { createGuardrailCall, getGuardrailsList } from "@/components/networking";

View file

@ -17,7 +17,7 @@ import {
InfoIcon,
CircleHelp,
} from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import {
listGuardrailSubmissions,
approveGuardrailSubmission,

View file

@ -1,5 +1,5 @@
import React, { useState, useCallback } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { SortingState } from "@tanstack/react-table";
import { Inbox, Plus, X } from "lucide-react";
import { useMCPToolsets } from "@/app/(dashboard)/hooks/mcpServers/useMCPToolsets";

View file

@ -1,7 +1,7 @@
import React from "react";
import { CircleAlert, Info } from "lucide-react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { z } from "zod/v4";
import { z } from "zod";
import { MCPServer, MCPUserEnvVarsStatus, MCPUserEnvVarSpec } from "@/components/mcp_tools/types";
import { clearMCPUserEnvVars, getMCPUserEnvVars, storeMCPUserEnvVars } from "@/components/networking";
import { toast } from "@/lib/toast";

View file

@ -2,7 +2,7 @@
import { CircleHelp } from "lucide-react";
import React, { useEffect, useState } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import type { MemoryRow } from "@/components/networking";
import { FieldGroup } from "@/components/ui/field";

View file

@ -2,7 +2,7 @@
import { CircleHelp } from "lucide-react";
import React from "react";
import { z } from "zod/v4";
import { z } from "zod";
import BudgetDurationDropdown from "@/components/common_components/budget_duration_dropdown";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";

View file

@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { CircleHelp } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import { Policy } from "@/components/policies/types";
import { teamListCall, keyListCall, modelAvailableCall, estimateAttachmentImpactCall } from "@/components/networking";
import { toast } from "@/lib/toast";

View file

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { Policy, PolicyCreateRequest, PolicyUpdateRequest } from "@/components/policies/types";
import { Guardrail } from "@/components/guardrails/types";
import { getResolvedGuardrails, modelAvailableCall } from "@/components/networking";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
export const ALL_TEAM_MODELS = "all-team-models";

View file

@ -1,6 +1,6 @@
import React, { useRef, useState } from "react";
import { Upload as UploadIcon, X } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import { convertPromptFileToJson, createPromptCall } from "@/components/networking";
import { toast } from "@/lib/toast";
import { Field, FieldDescription, FieldGroup, FieldSeparator, FieldTitle } from "@/components/ui/field";

View file

@ -3,7 +3,7 @@ import { useQuery } from "@tanstack/react-query";
import { CircleHelp } from "lucide-react";
import React, { useCallback, useMemo, useState } from "react";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { Logo } from "@/components/molecules/logo/Logo";
import { toast } from "@/lib/toast";
import { createSearchTool, fetchAvailableSearchProviders } from "@/components/networking";

View file

@ -1,7 +1,7 @@
import { isAdminRole } from "@/utils/roles";
import { useQuery } from "@tanstack/react-query";
import React, { useState } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import DeleteResourceModal from "@/components/common_components/DeleteResourceModal";
import { toast } from "@/lib/toast";
import {

View file

@ -1,6 +1,6 @@
import React, { useState } from "react";
import { CircleHelp } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import { toast } from "@/lib/toast";
import { registerClaudeCodePlugin } from "@/components/networking";
import { FieldGroup } from "@/components/ui/field";

View file

@ -2,7 +2,7 @@
import { ChevronRight, CircleHelp } from "lucide-react";
import React from "react";
import { z } from "zod/v4";
import { z } from "zod";
import BudgetDurationDropdown from "@/components/common_components/budget_duration_dropdown";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";

View file

@ -2,7 +2,7 @@
import React, { useState, useEffect } from "react";
import { SimpleTooltip } from "@/components/ui/tooltip";
import { z } from "zod/v4";
import { z } from "zod";
import { fetchUserModels } from "@/components/organisms/create_key_button";
import { getModelDisplayName } from "@/components/key_team_helpers/fetch_available_models_team_key";
import { tagInfoCall, tagUpdateCall } from "@/components/networking";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
import type { components } from "@/lib/http/schema";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
const isBlank = (value: string): boolean => value.trim() === "";

View file

@ -1,5 +1,5 @@
import React, { useMemo, useState } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { all_admin_roles } from "@/utils/roles";
import BudgetDurationDropdown from "@/components/common_components/budget_duration_dropdown";
import { ModelMaxBudget, ModelMaxBudgetField } from "@/components/key_team_helpers/ModelMaxBudgetEditor";

View file

@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
import { CircleHelp, Eye, EyeOff, Info } from "lucide-react";
import { Alert, AlertDescription, AlertTitle } from "@/components/shared/Alert";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { CredentialItem, vectorStoreCreateCall } from "@/components/networking";
import {
VectorStoreProviders,

View file

@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { ArrowLeft, CircleHelp, Lock } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import {
vectorStoreInfoCall,
vectorStoreUpdateCall,

View file

@ -21,7 +21,7 @@ import { consumeReturnUrl, getLoginUrl, getReturnUrl, isValidReturnUrl } from "@
import { CircleAlert, Info, TriangleAlert, X } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect, useId, useState } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { useWorker } from "@/hooks/useWorker";
const loginSchema = z.object({

View file

@ -1,6 +1,6 @@
import React from "react";
import { CircleAlert, Info } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import { Alert, AlertDescription, AlertTitle } from "@/components/shared/Alert";
import { PasswordInput } from "@/components/shared/PasswordInput";
import { Field, FieldLabel, FieldGroup } from "@/components/ui/field";

View file

@ -1,5 +1,5 @@
import { useEffect } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { useCloudZeroCreate } from "@/app/(dashboard)/hooks/cloudzero/useCloudZeroCreate";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";

View file

@ -1,5 +1,5 @@
import { useEffect } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { useCloudZeroUpdateSettings } from "@/app/(dashboard)/hooks/cloudzero/useCloudZeroSettings";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";

View file

@ -5,7 +5,7 @@ import { CircleHelp } from "lucide-react";
import type { Dayjs } from "dayjs";
import * as React from "react";
import { useForm, type Resolver } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { TagsInput } from "@/app/(dashboard)/guardrails/_components/content_filter/TagsInput";
import { FormField } from "@/components/shared/form/FormField";

View file

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { keyCreateCall } from "./networking";
import { CopyToClipboard } from "react-copy-to-clipboard";
import { CircleAlert, CirclePlus, Copy, Info, KeyRound, Link } from "lucide-react";

View file

@ -5,7 +5,7 @@ import { useUpdateCyberArkConfig } from "@/app/(dashboard)/hooks/configOverrides
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { toast } from "@/lib/toast";
import React, { useMemo } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";
import { PasswordInput } from "@/components/shared/PasswordInput";

View file

@ -5,7 +5,7 @@ import { useUpdateHashicorpVaultConfig } from "@/app/(dashboard)/hooks/configOve
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { toast } from "@/lib/toast";
import React, { useMemo } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";
import { PasswordInput } from "@/components/shared/PasswordInput";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
const IPV4 = "(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}";
const SEG = "[a-fA-F\\d]{1,4}";

View file

@ -2,7 +2,7 @@
import React from "react";
import { FormProvider, useFormContext, useWatch, type UseFormReturn } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { ssoProviderLogoMap, ssoProviderDisplayNames } from "../constants";
import { Logo } from "@/components/molecules/logo/Logo";
import { FieldGroup } from "@/components/ui/field";

View file

@ -1,7 +1,7 @@
"use client";
import { Controller } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings";
import { useUpdateUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUpdateUISettings";

View file

@ -18,7 +18,7 @@ import { TagsInput } from "@/app/(dashboard)/guardrails/_components/content_filt
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ChevronDown, Plus, Users } from "lucide-react";
import React, { useEffect, useMemo, useState } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { PageHeader } from "@/components/shared/PageHeader";
import { Button as UIButton } from "@/components/ui/button";

View file

@ -1,7 +1,7 @@
import { CircleHelp } from "lucide-react";
import React, { useEffect, useState } from "react";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";

View file

@ -7,7 +7,7 @@ import { getForecastConfigError, isForecastClassifier } from "../add_model/forec
import React, { useEffect, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";
import { Button } from "@/components/ui/button";

View file

@ -24,10 +24,10 @@ export const buildSavedJevConnectionTestRequest = (
const result = z
.object({
classifier_type: z.literal("jev"),
tiers: z.record(z.unknown()),
jev_classifier_config: jevClassifierConfigSchema.default({}),
tiers: z.record(z.string(), z.unknown()),
jev_classifier_config: jevClassifierConfigSchema.prefault({}),
})
.passthrough()
.loose()
.safeParse(parsed);
if (!result.success) return undefined;
return {

View file

@ -7,7 +7,8 @@ const jevClassifierConfigFields = {
instructions: z
.string()
.nullish()
.transform((value) => value ?? undefined),
.transform((value) => value ?? undefined)
.optional(),
circuit_breaker_enabled: z.boolean().optional(),
circuit_breaker_cooldown_seconds: z.number().finite().positive().optional(),
};

View file

@ -4,7 +4,7 @@ import React, { useState } from "react";
import { CircleHelp, Info, Plug } from "lucide-react";
import { Alert, AlertDescription, AlertTitle } from "@/components/shared/Alert";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { createPassThroughEndpoint } from "./networking";
import NumericalInput from "./shared/numerical_input";

View file

@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { CircleCheck, FileDown } from "lucide-react";
import { z } from "zod/v4";
import { z } from "zod";
import { getGlobalLitellmHeaderName } from "@/components/networking";
import { toast } from "@/lib/toast";
import { Alert, AlertDescription, AlertTitle } from "@/components/shared/Alert";

View file

@ -2,7 +2,7 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";
import { describe, expect, it, vi } from "vitest";
import { z } from "zod/v4";
import { z } from "zod";
import { TeamMetadataField } from "@/app/(dashboard)/hooks/teams/useTeamMetadataSchema";
import { useZodForm } from "@/lib/forms/useZodForm";
import MetadataKeyValueFields, {

View file

@ -8,7 +8,7 @@ import {
type FieldValues,
type UseFormGetValues,
} from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { TeamMetadataField } from "@/app/(dashboard)/hooks/teams/useTeamMetadataSchema";
import { FormField } from "@/components/shared/form/FormField";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
const sharedShape = {
auto_router_name: z.string().min(1, "Auto router name is required"),

View file

@ -1,4 +1,3 @@
import "openai/shims/web";
import { act, fireEvent, render, screen, waitFor, within } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

View file

@ -250,7 +250,7 @@ describe("fixed management operations", () => {
it("provides strict JSON schemas for nullable and transformed tool arguments", async () => {
const model = transport([completion()]);
await runLiteAdmin(options(), model.client);
const tools = model.requests[0].tools!;
const tools = model.requests[0].tools!.filter((tool) => tool.type === "function");
for (const tool of tools) expect(tool.function.strict).toBe(true);
const createUser = tools.find((tool) => tool.function.name === "user_create")!;
const expectedSchema = {

View file

@ -105,7 +105,7 @@ export async function runLiteAdmin(options: LiteAdminOptions, client?: OpenAI):
max_tokens: 2_048,
};
const runnerOptions = { signal: options.signal, maxChatCompletions: 6, maxRetries: 0, timeout: 60_000 };
const runner = modelClient.beta.chat.completions.runTools(parameters, runnerOptions);
const runner = modelClient.chat.completions.runTools(parameters, runnerOptions);
runner.on("chatCompletion", (completion) => {
active();
const message = completion.choices[0]?.message;

View file

@ -27,8 +27,12 @@ export interface OperationContext {
type Schemas = components["schemas"];
const text = z.string().min(1).max(200);
const hash = z.string().regex(/^[a-f0-9]{64}$/i, "Use the key hash from a lookup, not a raw API key.");
const optional = <Schema extends z.ZodType<unknown>>(schema: Schema) =>
schema.nullable().transform((value) => value ?? undefined);
const optional = <Schema extends z.ZodType<unknown>>(schema: Schema) => schema.nullable();
type NullsStripped<T> = { [K in keyof T]: Exclude<T[K], null> };
const stripNulls = <T extends Record<string, unknown>>(args: T): NullsStripped<T> =>
Object.fromEntries(
Object.entries(args).map(([key, value]) => [key, value === null ? undefined : value]),
) as NullsStripped<T>;
const optionalText = optional(text);
const amount = optional(z.number().finite().nonnegative());
const limit = optional(z.number().int().nonnegative());
@ -47,15 +51,15 @@ const keyFields = {
};
const teamFields = { team_alias: optionalText, organization_id: optionalText, models, ...limits };
const userFields = {
user_email: optional(z.string().email().max(200)),
user_email: optional(z.email().max(200)),
user_alias: optionalText,
user_role: optional(z.enum(["proxy_admin", "proxy_admin_viewer", "internal_user", "internal_user_viewer"])),
models,
...limits,
};
const object = <Shape extends z.ZodRawShape>(shape: Shape) => z.object(shape).strict();
const object = <Shape extends z.ZodRawShape>(shape: Shape) => z.strictObject(shape);
const dated = <Shape extends z.ZodRawShape>(shape: Shape) =>
object({ start_date: z.string().date(), end_date: z.string().date(), ...shape }).refine((value) => {
object({ start_date: z.iso.date(), end_date: z.iso.date(), ...shape }).refine((value: Record<string, unknown>) => {
if (typeof value.start_date !== "string" || typeof value.end_date !== "string") return false;
const days = (Date.parse(value.end_date) - Date.parse(value.start_date)) / 86_400_000;
return days >= 0 && days <= 366;
@ -108,18 +112,19 @@ export function createLiteAdminOperations(context: OperationContext) {
};
const auth = { accessToken: context.accessToken, signal: context.signal };
const operation =
(mode: "read" | "write" | "delete", kind: ResultKind) =>
(mode: "read" | "write" | "delete", kind: ResultKind, extraArguments?: Record<string, unknown>) =>
<Schema extends z.ZodType<Record<string, unknown>>>(
name: string,
title: string,
schema: Schema,
execute: (args: z.output<Schema>) => Promise<unknown>,
execute: (args: NullsStripped<z.output<Schema>>) => Promise<unknown>,
) => {
const definition = {
name,
description: `${title}. Null means omitted or unchanged. ${mode === "read" ? "Read-only." : "Requires the administrator to review and confirm the change."}`,
parameters: schema,
function: async (args: z.output<Schema>) => {
function: async (rawArgs: unknown) => {
const args = stripNulls(rawArgs as z.output<Schema>);
active();
context.beforeTool();
const action: LiteAdminAction | undefined =
@ -129,7 +134,10 @@ export function createLiteAdminOperations(context: OperationContext) {
id: crypto.randomUUID(),
name,
title,
arguments: Object.fromEntries(Object.entries(args).filter(([, value]) => value !== undefined)),
arguments: {
...Object.fromEntries(Object.entries(args).filter(([, value]) => value !== undefined)),
...extraArguments,
},
destructive: mode === "delete",
};
if (action) {
@ -140,7 +148,7 @@ export function createLiteAdminOperations(context: OperationContext) {
const outcome = await Promise.resolve()
.then(() => {
active();
return execute(args);
return execute({ ...args, ...extraArguments } as NullsStripped<z.output<Schema>>);
})
.then(
(value) => ({ ok: true, value }) as const,
@ -256,10 +264,10 @@ export function createLiteAdminOperations(context: OperationContext) {
operation("read", "user")("user_info", "View a user", object({ user_id: text }), (a) =>
apiClient.get<unknown>("/v2/user/info", { ...auth, query: a }),
),
operation("write", "user")(
operation("write", "user", { auto_create_key: false })(
"user_create",
"Create a user without a key",
object({ user_id: optionalText, ...userFields }).transform((a) => ({ ...a, auto_create_key: false })),
object({ user_id: optionalText, ...userFields }),
(a) => apiClient.post<unknown>("/user/new", { ...auth, body: a satisfies Partial<Schemas["NewUserRequest"]> }),
),
operation("write", "user")("user_update", "Update a user", object({ user_id: text, ...userFields }), (a) =>

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
import { MCPServer, MCPToolset } from "../mcp_tools/types";
import { MCP_ALL_TOOLS_WILDCARD } from "../mcp_tools/constants";

View file

@ -1,5 +1,5 @@
import React from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";
import { Button } from "@/components/ui/button";

View file

@ -6,7 +6,7 @@ import { Check, CircleHelp, Copy, RefreshCw, TriangleAlert } from "lucide-react"
import React, { useEffect, useMemo, useState } from "react";
import { useWatch } from "react-hook-form";
import { CopyToClipboard } from "react-copy-to-clipboard";
import { z } from "zod/v4";
import { z } from "zod";
import { KeyResponse } from "../key_team_helpers/key_list";
import { toast } from "@/lib/toast";
import { regenerateKeyCall } from "../networking";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
import type { components } from "@/lib/http/schema";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
import type { Organization } from "@/components/networking";
import type { components } from "@/lib/http/schema";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
const isBlank = (value: string): boolean => value.trim() === "";

View file

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { updatePassThroughEndpoint, deletePassThroughEndpointsCall } from "./networking";
import { Eye, EyeOff } from "lucide-react";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import RoutePreview from "./route_preview";
import { toast } from "@/lib/toast";
import PassThroughSecuritySection from "./common_components/PassThroughSecuritySection";

View file

@ -2,7 +2,7 @@
import React, { useEffect, useMemo } from "react";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { FieldGroup } from "@/components/ui/field";
import { FormField } from "@/components/shared/form/FormField";
import {

View file

@ -4,7 +4,7 @@ import userEvent from "@testing-library/user-event";
import * as React from "react";
import { useForm } from "react-hook-form";
import { describe, expect, it, vi } from "vitest";
import { z } from "zod/v4";
import { z } from "zod";
import { Input } from "@/components/ui/input";

View file

@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useState } from "react";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import { z } from "zod/v4";
import { z } from "zod";
import NumericalInput from "../shared/numerical_input";
import BudgetDurationDropdown from "../common_components/budget_duration_dropdown";
import { FieldGroup } from "@/components/ui/field";

View file

@ -2,7 +2,7 @@
import { Save } from "lucide-react";
import { useWatch } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import { FormField } from "@/components/shared/form/FormField";
import { Button } from "@/components/ui/button";

View file

@ -47,7 +47,7 @@ import { toast } from "@/lib/toast";
import { CheckIcon, ChevronDown, CircleMinus, CopyIcon, Info, Pencil, Plus, Save } from "lucide-react";
import React, { useEffect, useMemo, useState } from "react";
import { useFieldArray } from "react-hook-form";
import { z } from "zod/v4";
import { z } from "zod";
import GuardrailsSelect from "./GuardrailsSelect";
import {
type CallerEditAccess,

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
export const TEAM_ADMIN_EDITABLE_TEAM_FIELDS_SETTING = "team_admin_editable_team_fields";

View file

@ -1,4 +1,4 @@
import { z } from "zod/v4";
import { z } from "zod";
import { KeyResponse } from "../key_team_helpers/key_list";
import { extractLoggingSettings, formatMetadataForDisplay, stripTagsFromMetadata } from "../key_info_utils";
@ -122,50 +122,52 @@ export const toKeyEditFormValues = (keyData: KeyResponse): KeyEditFormValues =>
});
export const keyEditFormSchema = z.object({
key_alias: z.custom<string | undefined>(),
models: z.custom<string[] | undefined>(),
allowed_routes: z.custom<string | undefined>(),
max_budget: z.custom<number | string | null | undefined>(),
soft_budget: z.custom<number | string | null | undefined>(),
budget_duration: z.custom<string | null | undefined>(),
tpm_limit: z.custom<number | string | null | undefined>(),
tpm_limit_type: z.custom<string | null | undefined>(),
rpm_limit: z.custom<number | string | null | undefined>(),
rpm_limit_type: z.custom<string | null | undefined>(),
tpd_limit: z.custom<number | string | null | undefined>(),
throttle_on_budget_exceeded: z.custom<boolean | undefined>(),
enable_prompt_caching: z.custom<boolean | undefined>(),
max_parallel_requests: z.custom<number | string | null | undefined>(),
model_tpm_limit: z.custom<string | undefined>(),
model_rpm_limit: z.custom<string | undefined>(),
key_alias: z.custom<string | undefined>().optional(),
models: z.custom<string[] | undefined>().optional(),
allowed_routes: z.custom<string | undefined>().optional(),
max_budget: z.custom<number | string | null | undefined>().optional(),
soft_budget: z.custom<number | string | null | undefined>().optional(),
budget_duration: z.custom<string | null | undefined>().optional(),
tpm_limit: z.custom<number | string | null | undefined>().optional(),
tpm_limit_type: z.custom<string | null | undefined>().optional(),
rpm_limit: z.custom<number | string | null | undefined>().optional(),
rpm_limit_type: z.custom<string | null | undefined>().optional(),
tpd_limit: z.custom<number | string | null | undefined>().optional(),
throttle_on_budget_exceeded: z.custom<boolean | undefined>().optional(),
enable_prompt_caching: z.custom<boolean | undefined>().optional(),
max_parallel_requests: z.custom<number | string | null | undefined>().optional(),
model_tpm_limit: z.custom<string | undefined>().optional(),
model_rpm_limit: z.custom<string | undefined>().optional(),
default_estimated_output_tokens: z
.custom<number | string | null | undefined>()
.refine(estimateChecks.positive.isValid, estimateChecks.positive.message),
.refine(estimateChecks.positive.isValid, estimateChecks.positive.message)
.optional(),
default_estimated_output_tokens_per_model: z
.custom<string | undefined>()
.refine(estimateChecks.perModel.isValid, estimateChecks.perModel.message),
guardrails: z.custom<string[] | undefined>(),
disable_global_guardrails: z.custom<boolean | undefined>(),
policies: z.custom<string[] | undefined>(),
tags: z.custom<string[] | undefined>(),
prompts: z.custom<string[] | undefined>(),
access_group_ids: z.custom<string[] | undefined>(),
allowed_passthrough_routes: z.custom<string[] | undefined>(),
vector_stores: z.custom<string[] | undefined>(),
mcp_servers_and_groups: z.custom<McpServersAndGroups | undefined>(),
mcp_tool_permissions: z.custom<Record<string, string[]> | undefined>(),
agents_and_groups: z.custom<AgentsAndGroups | undefined>(),
skills: z.custom<string[] | undefined>(),
organization_id: z.custom<string | null | undefined>(),
team_id: z.custom<string | null | undefined>(),
.refine(estimateChecks.perModel.isValid, estimateChecks.perModel.message)
.optional(),
guardrails: z.custom<string[] | undefined>().optional(),
disable_global_guardrails: z.custom<boolean | undefined>().optional(),
policies: z.custom<string[] | undefined>().optional(),
tags: z.custom<string[] | undefined>().optional(),
prompts: z.custom<string[] | undefined>().optional(),
access_group_ids: z.custom<string[] | undefined>().optional(),
allowed_passthrough_routes: z.custom<string[] | undefined>().optional(),
vector_stores: z.custom<string[] | undefined>().optional(),
mcp_servers_and_groups: z.custom<McpServersAndGroups | undefined>().optional(),
mcp_tool_permissions: z.custom<Record<string, string[]> | undefined>().optional(),
agents_and_groups: z.custom<AgentsAndGroups | undefined>().optional(),
skills: z.custom<string[] | undefined>().optional(),
organization_id: z.custom<string | null | undefined>().optional(),
team_id: z.custom<string | null | undefined>().optional(),
project_id: z.string().nullable().optional(),
logging_settings: z.custom<unknown[] | undefined>(),
metadata: z.custom<string | undefined>(),
duration: z.custom<string | null | undefined>(),
token: z.custom<string | undefined>(),
disabled_callbacks: z.custom<string[] | undefined>(),
auto_rotate: z.custom<boolean | undefined>(),
rotation_interval: z.custom<string | undefined>(),
logging_settings: z.custom<unknown[] | undefined>().optional(),
metadata: z.custom<string | undefined>().optional(),
duration: z.custom<string | null | undefined>().optional(),
token: z.custom<string | undefined>().optional(),
disabled_callbacks: z.custom<string[] | undefined>().optional(),
auto_rotate: z.custom<boolean | undefined>().optional(),
rotation_interval: z.custom<string | undefined>().optional(),
});
export interface MountedFieldGates {

View file

@ -1,6 +1,6 @@
import { TriangleAlert } from "lucide-react";
import { useState } from "react";
import { z } from "zod/v4";
import { z } from "zod";
import { modelPatchUpdateCall } from "./networking";
import { toast } from "@/lib/toast";
import { FieldGroup } from "@/components/ui/field";

View file

@ -2,7 +2,7 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import * as React from "react";
import { describe, expect, it, vi } from "vitest";
import { z } from "zod/v4";
import { z } from "zod";
import { useZodForm } from "./useZodForm";

View file

@ -2,17 +2,27 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm, type FieldValues, type UseFormProps, type UseFormReturn } from "react-hook-form";
import type { $ZodType } from "zod/v4/core";
import { z } from "zod";
type FormValuesOf<T> = Extract<T, FieldValues>;
// TInput is what the widgets hold (strings), TOutput is what handleSubmit receives after
// zod runs coerce/transform; typing useForm with z.infer would collapse the two and lie
// about defaultValues. zod's $ZodType declares them as <Output, Input>, in that order.
// The `unknown` in the middle is RHF's context generic, which we never use.
export const useZodForm = <TInput extends FieldValues, TOutput extends FieldValues>(
schema: $ZodType<TOutput, TInput>,
// about defaultValues. The `unknown` in the middle is RHF's context generic, which we never use.
export function useZodForm<Schema extends z.core.$ZodType>(
schema: Schema,
props?: Omit<UseFormProps<FormValuesOf<z.input<Schema>>, unknown, FormValuesOf<z.output<Schema>>>, "resolver">,
): UseFormReturn<FormValuesOf<z.input<Schema>>, unknown, FormValuesOf<z.output<Schema>>>;
export function useZodForm<TInput extends FieldValues, TOutput extends FieldValues>(
schema: z.core.$ZodType<TOutput, TInput>,
props?: Omit<UseFormProps<TInput, unknown, TOutput>, "resolver">,
): UseFormReturn<TInput, unknown, TOutput> =>
useForm<TInput, unknown, TOutput>({
): UseFormReturn<TInput, unknown, TOutput>;
export function useZodForm(
schema: z.core.$ZodType,
props?: Omit<UseFormProps<FieldValues, unknown, FieldValues>, "resolver">,
): UseFormReturn<FieldValues, unknown, FieldValues> {
return useForm<FieldValues, unknown, FieldValues>({
...props,
resolver: zodResolver(schema),
resolver: zodResolver(schema as z.core.$ZodType<FieldValues, FieldValues>),
});
}