Update ai validation to use gpt-5 and the new responses api
This commit is contained in:
133
inventory-server/package-lock.json
generated
133
inventory-server/package-lock.json
generated
@@ -20,7 +20,7 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"mysql2": "^3.12.0",
|
"mysql2": "^3.12.0",
|
||||||
"openai": "^4.85.3",
|
"openai": "^6.0.0",
|
||||||
"pg": "^8.14.1",
|
"pg": "^8.14.1",
|
||||||
"pm2": "^5.3.0",
|
"pm2": "^5.3.0",
|
||||||
"ssh2": "^1.16.0",
|
"ssh2": "^1.16.0",
|
||||||
@@ -399,43 +399,12 @@
|
|||||||
"integrity": "sha512-R/BHQFripuhW6XPXy05hIvXJQdQ4540KnTvEFHSLjXfHYM41liOLKgIJEyYYiQe796xpaMHfe4Uj/p7Uvng2vA==",
|
"integrity": "sha512-R/BHQFripuhW6XPXy05hIvXJQdQ4540KnTvEFHSLjXfHYM41liOLKgIJEyYYiQe796xpaMHfe4Uj/p7Uvng2vA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
|
||||||
"version": "18.19.76",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.76.tgz",
|
|
||||||
"integrity": "sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"undici-types": "~5.26.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/node-fetch": {
|
|
||||||
"version": "2.6.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
|
|
||||||
"integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "*",
|
|
||||||
"form-data": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/abbrev": {
|
"node_modules/abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"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/accepts": {
|
"node_modules/accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
@@ -458,18 +427,6 @@
|
|||||||
"node": ">= 14"
|
"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/amp": {
|
"node_modules/amp": {
|
||||||
"version": "0.3.1",
|
"version": "0.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz",
|
||||||
@@ -1327,15 +1284,6 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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/eventemitter2": {
|
"node_modules/eventemitter2": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz",
|
||||||
@@ -1474,25 +1422,6 @@
|
|||||||
"node": ">= 6"
|
"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/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/forwarded": {
|
"node_modules/forwarded": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
@@ -1853,15 +1782,6 @@
|
|||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"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/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
@@ -2407,25 +2327,6 @@
|
|||||||
"integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==",
|
"integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"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==",
|
|
||||||
"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-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
@@ -2622,25 +2523,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/openai": {
|
"node_modules/openai": {
|
||||||
"version": "4.85.3",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/openai/-/openai-4.85.3.tgz",
|
"resolved": "https://registry.npmjs.org/openai/-/openai-6.0.0.tgz",
|
||||||
"integrity": "sha512-KTMXAK6FPd2IvsPtglMt0J1GyVrjMxCYzu/mVbCPabzzquSJoZlYpHtE0p0ScZPyt11XTc757xSO4j39j5g+Xw==",
|
"integrity": "sha512-J7LEmTn3WLZnbyEmMYcMPyT5A0fGzhPwSvVUcNRKy6j2hJIbqSFrJERnUHYNkcoCCalRumypnj9AVoe5bVHd3Q==",
|
||||||
"license": "Apache-2.0",
|
"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": {
|
"bin": {
|
||||||
"openai": "bin/cli"
|
"openai": "bin/cli"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"ws": "^8.18.0",
|
"ws": "^8.18.0",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.25 || ^4.0"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"ws": {
|
"ws": {
|
||||||
@@ -3941,12 +3833,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"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/unpipe": {
|
"node_modules/unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
@@ -4017,15 +3903,6 @@
|
|||||||
"lodash": "^4.17.14"
|
"lodash": "^4.17.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"mysql2": "^3.12.0",
|
"mysql2": "^3.12.0",
|
||||||
"openai": "^4.85.3",
|
"openai": "^6.0.0",
|
||||||
"pg": "^8.14.1",
|
"pg": "^8.14.1",
|
||||||
"pm2": "^5.3.0",
|
"pm2": "^5.3.0",
|
||||||
"ssh2": "^1.16.0",
|
"ssh2": "^1.16.0",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const path = require("path");
|
|||||||
const dotenv = require("dotenv");
|
const dotenv = require("dotenv");
|
||||||
const mysql = require('mysql2/promise');
|
const mysql = require('mysql2/promise');
|
||||||
const { Client } = require('ssh2');
|
const { Client } = require('ssh2');
|
||||||
const { getDbConnection } = require('../utils/dbConnection'); // Import the optimized connection function
|
const { getDbConnection, closeAllConnections } = require('../utils/dbConnection'); // Import the optimized connection function
|
||||||
|
|
||||||
// Ensure environment variables are loaded
|
// Ensure environment variables are loaded
|
||||||
dotenv.config({ path: path.join(__dirname, "../../.env") });
|
dotenv.config({ path: path.join(__dirname, "../../.env") });
|
||||||
@@ -19,6 +19,121 @@ if (!process.env.OPENAI_API_KEY) {
|
|||||||
console.error("Warning: OPENAI_API_KEY is not set in environment variables");
|
console.error("Warning: OPENAI_API_KEY is not set in environment variables");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createResponsesCompletion(payload) {
|
||||||
|
if (!openai.responses?.create) {
|
||||||
|
throw new Error(
|
||||||
|
"OpenAI client does not expose responses.create; please verify the openai SDK version."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return openai.responses.create(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
const AI_VALIDATION_SCHEMA_NAME = "ai_validation_response";
|
||||||
|
|
||||||
|
const FLEXIBLE_PRIMITIVE_SCHEMAS = [
|
||||||
|
{ type: "string" },
|
||||||
|
{ type: "number" },
|
||||||
|
{ type: "boolean" },
|
||||||
|
{ type: "null" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const FLEXIBLE_ARRAY_SCHEMA = {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
anyOf: FLEXIBLE_PRIMITIVE_SCHEMAS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const FLEXIBLE_OBJECT_SCHEMA = {
|
||||||
|
type: "object",
|
||||||
|
properties: {},
|
||||||
|
patternProperties: {
|
||||||
|
".+": {
|
||||||
|
anyOf: [...FLEXIBLE_PRIMITIVE_SCHEMAS, FLEXIBLE_ARRAY_SCHEMA],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const FLEXIBLE_VALUE_SCHEMA = {
|
||||||
|
anyOf: [...FLEXIBLE_PRIMITIVE_SCHEMAS, FLEXIBLE_ARRAY_SCHEMA, FLEXIBLE_OBJECT_SCHEMA],
|
||||||
|
};
|
||||||
|
|
||||||
|
const AI_VALIDATION_JSON_SCHEMA = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: false,
|
||||||
|
required: [
|
||||||
|
"correctedData",
|
||||||
|
"changes",
|
||||||
|
"warnings",
|
||||||
|
"summary",
|
||||||
|
"qualityNotes",
|
||||||
|
"nextSteps",
|
||||||
|
"metadata"
|
||||||
|
],
|
||||||
|
properties: {
|
||||||
|
correctedData: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
properties: {},
|
||||||
|
patternProperties: {
|
||||||
|
".+": FLEXIBLE_VALUE_SCHEMA,
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
changes: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
warnings: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
type: "string",
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
qualityNotes: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
nextSteps: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
type: "object",
|
||||||
|
properties: {},
|
||||||
|
patternProperties: {
|
||||||
|
".+": FLEXIBLE_VALUE_SCHEMA,
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const AI_VALIDATION_TEXT_FORMAT = {
|
||||||
|
type: "json_schema",
|
||||||
|
name: AI_VALIDATION_SCHEMA_NAME,
|
||||||
|
strict: true,
|
||||||
|
schema: AI_VALIDATION_JSON_SCHEMA,
|
||||||
|
};
|
||||||
|
|
||||||
// Debug endpoint for viewing prompt
|
// Debug endpoint for viewing prompt
|
||||||
router.post("/debug", async (req, res) => {
|
router.post("/debug", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
@@ -139,6 +254,12 @@ router.post("/debug", async (req, res) => {
|
|||||||
code: error.code || null,
|
code: error.code || null,
|
||||||
name: error.name || null
|
name: error.name || null
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
await closeAllConnections();
|
||||||
|
} catch (closeError) {
|
||||||
|
console.error("⚠️ Failed to close DB connections after debug request:", closeError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -402,8 +523,9 @@ async function generateDebugResponse(productsToUse, res) {
|
|||||||
|
|
||||||
console.log("Sending response with taxonomy stats:", response.taxonomyStats);
|
console.log("Sending response with taxonomy stats:", response.taxonomyStats);
|
||||||
return response;
|
return response;
|
||||||
} finally {
|
} catch (promptLoadError) {
|
||||||
if (promptConnection) await promptConnection.end();
|
console.error("Error loading prompt:", promptLoadError);
|
||||||
|
throw promptLoadError;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error generating debug response:", error);
|
console.error("Error generating debug response:", error);
|
||||||
@@ -883,34 +1005,80 @@ router.post("/validate", async (req, res) => {
|
|||||||
console.log("🔄 Loading prompt with filtered taxonomy...");
|
console.log("🔄 Loading prompt with filtered taxonomy...");
|
||||||
const promptData = await loadPrompt(connection, products, req.app.locals.pool);
|
const promptData = await loadPrompt(connection, products, req.app.locals.pool);
|
||||||
const fullUserPrompt = promptData.userContent + "\n" + JSON.stringify(products);
|
const fullUserPrompt = promptData.userContent + "\n" + JSON.stringify(products);
|
||||||
const promptLength = promptData.systemInstructions.length + fullUserPrompt.length; // Store prompt length for performance metrics
|
promptLength = promptData.systemInstructions.length + fullUserPrompt.length; // Store prompt length for performance metrics
|
||||||
console.log("📝 Generated prompt length:", promptLength);
|
console.log("📝 Generated prompt length:", promptLength);
|
||||||
console.log("📝 System instructions length:", promptData.systemInstructions.length);
|
console.log("📝 System instructions length:", promptData.systemInstructions.length);
|
||||||
console.log("📝 User content length:", fullUserPrompt.length);
|
console.log("📝 User content length:", fullUserPrompt.length);
|
||||||
|
|
||||||
console.log("🤖 Sending request to OpenAI...");
|
console.log("🤖 Sending request to OpenAI Responses API...");
|
||||||
const completion = await openai.chat.completions.create({
|
|
||||||
model: "gpt-4o",
|
// GPT-5 Responses API Configuration:
|
||||||
messages: [
|
// - Using "gpt-5" (reasoning model) for complex product validation
|
||||||
|
// - reasoning.effort: "medium" balances quality and speed (minimal, low, medium, high)
|
||||||
|
// - text.verbosity: "medium" provides balanced output detail (low, medium, high)
|
||||||
|
// - max_output_tokens: 20000 ensures space for large product batches
|
||||||
|
// Note: Responses API is the recommended endpoint for GPT-5 models
|
||||||
|
const completion = await createResponsesCompletion({
|
||||||
|
model: "gpt-5",
|
||||||
|
input: [
|
||||||
{
|
{
|
||||||
role: "system",
|
role: "developer",
|
||||||
content: promptData.systemInstructions,
|
content: `${promptData.systemInstructions}\n\nYou MUST respond with a single valid JSON object containing the following top-level keys: correctedData, changes, warnings, summary, qualityNotes, nextSteps, metadata.\n- correctedData: array of product objects reflecting the updated data.\n- changes: array of human-readable bullet points summarizing the nature of updates.\n- warnings: array of caveats or risks that still require review.\n- summary: a concise paragraph (<=75 words) describing overall data quality and improvements.\n- qualityNotes: array of short comments (<=40 words each) about validation quality or notable observations.\n- nextSteps: array of recommended manual follow-up actions (if none, provide an empty array).\n- metadata: object containing any supplemental machine-readable information (optional fields allowed).\nDo NOT include Markdown code fences or any text outside the JSON object.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
role: "user",
|
role: "user",
|
||||||
content: fullUserPrompt,
|
content: fullUserPrompt,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
temperature: 0.2,
|
reasoning: {
|
||||||
response_format: { type: "json_object" },
|
effort: "medium"
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
verbosity: "medium",
|
||||||
|
format: AI_VALIDATION_TEXT_FORMAT,
|
||||||
|
},
|
||||||
|
max_output_tokens: 20000,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("✅ Received response from OpenAI");
|
console.log("✅ Received response from OpenAI Responses API");
|
||||||
const rawResponse = completion.choices[0].message.content;
|
|
||||||
console.log("📄 Raw AI response length:", rawResponse.length);
|
// Responses API structure: response has 'output' array with message objects
|
||||||
|
const rawResponse = extractResponseText(completion);
|
||||||
|
console.log("📄 Raw AI response length:", rawResponse ? rawResponse.length : 0);
|
||||||
|
|
||||||
|
if (!rawResponse) {
|
||||||
|
throw new Error("OpenAI response did not include any text output");
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseModel = completion.model;
|
||||||
|
const usage = completion.usage || {};
|
||||||
|
|
||||||
|
// GPT-5 Responses API provides detailed token usage including reasoning tokens
|
||||||
|
const tokenUsageSummary = {
|
||||||
|
prompt: usage.input_tokens ?? usage.prompt_tokens ?? null,
|
||||||
|
completion: usage.output_tokens ?? usage.completion_tokens ?? null,
|
||||||
|
total: usage.total_tokens ?? null,
|
||||||
|
// GPT-5 reasoning tokens are in output_tokens_details
|
||||||
|
reasoning: usage.output_tokens_details?.reasoning_tokens ?? usage.completion_tokens_details?.reasoning_tokens ?? null,
|
||||||
|
// Also capture text generation tokens separately from reasoning
|
||||||
|
textGeneration: usage.output_tokens_details?.text_generation_tokens ?? usage.completion_tokens_details?.text_generation_tokens ?? null,
|
||||||
|
cachedPrompt: usage.input_tokens_details?.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? null,
|
||||||
|
// Capture audio tokens if present (future GPT-5 feature)
|
||||||
|
audioTokens: usage.output_tokens_details?.audio_tokens ?? usage.completion_tokens_details?.audio_tokens ?? null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract reasoning_effort and verbosity that were actually applied
|
||||||
|
const reasoningEffortApplied = completion.reasoning?.effort || "medium";
|
||||||
|
const verbosityApplied = completion.text?.verbosity || "medium";
|
||||||
|
|
||||||
|
console.log("📊 Token usage summary:", tokenUsageSummary);
|
||||||
|
console.log("🤖 Model dispatched:", responseModel);
|
||||||
|
console.log("🧠 Reasoning effort applied:", reasoningEffortApplied);
|
||||||
|
console.log("📝 Verbosity applied:", verbosityApplied);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const aiResponse = JSON.parse(rawResponse);
|
const normalizedResponse = normalizeJsonResponse(rawResponse);
|
||||||
|
const aiResponse = JSON.parse(normalizedResponse);
|
||||||
console.log(
|
console.log(
|
||||||
"🔄 Parsed AI response with keys:",
|
"🔄 Parsed AI response with keys:",
|
||||||
Object.keys(aiResponse)
|
Object.keys(aiResponse)
|
||||||
@@ -975,7 +1143,12 @@ router.post("/validate", async (req, res) => {
|
|||||||
const endTime = new Date();
|
const endTime = new Date();
|
||||||
let performanceMetrics = {
|
let performanceMetrics = {
|
||||||
promptLength,
|
promptLength,
|
||||||
productCount: products.length
|
productCount: products.length,
|
||||||
|
model: responseModel,
|
||||||
|
tokenUsage: tokenUsageSummary,
|
||||||
|
reasoningTokens: tokenUsageSummary.reasoning,
|
||||||
|
reasoningEffort: reasoningEffortApplied,
|
||||||
|
verbosity: verbosityApplied,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1040,6 +1213,11 @@ router.post("/validate", async (req, res) => {
|
|||||||
let promptSources = null;
|
let promptSources = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Use the local PostgreSQL pool from the app
|
||||||
|
const pool = req.app.locals.pool;
|
||||||
|
if (!pool) {
|
||||||
|
console.warn("⚠️ Local database pool not available for prompt sources");
|
||||||
|
} else {
|
||||||
// Get system prompt
|
// Get system prompt
|
||||||
const systemPromptResult = await pool.query(`
|
const systemPromptResult = await pool.query(`
|
||||||
SELECT * FROM ai_prompts WHERE prompt_type = 'system'
|
SELECT * FROM ai_prompts WHERE prompt_type = 'system'
|
||||||
@@ -1070,25 +1248,14 @@ router.post("/validate", async (req, res) => {
|
|||||||
companyPrompts = companyPromptsResult.rows;
|
companyPrompts = companyPromptsResult.rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find company names from taxonomy for the validation endpoint
|
// Format company prompts for response
|
||||||
const companyPromptsWithNames = companyPrompts.map(prompt => {
|
// Note: Company names would require re-fetching taxonomy data
|
||||||
let companyName = "Unknown Company";
|
// For now, we include company ID only
|
||||||
if (taxonomy.companies && Array.isArray(taxonomy.companies)) {
|
const companyPromptsWithNames = companyPrompts.map(prompt => ({
|
||||||
const companyData = taxonomy.companies.find(company =>
|
|
||||||
String(company[0]) === String(prompt.company)
|
|
||||||
);
|
|
||||||
if (companyData && companyData[1]) {
|
|
||||||
companyName = companyData[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: prompt.id,
|
id: prompt.id,
|
||||||
company: prompt.company,
|
company: prompt.company,
|
||||||
companyName: companyName,
|
|
||||||
prompt_text: prompt.prompt_text
|
prompt_text: prompt.prompt_text
|
||||||
};
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Set prompt sources
|
// Set prompt sources
|
||||||
if (generalPromptResult.rows.length > 0) {
|
if (generalPromptResult.rows.length > 0) {
|
||||||
@@ -1118,6 +1285,7 @@ router.post("/validate", async (req, res) => {
|
|||||||
companyPrompts: companyPromptsWithNames
|
companyPrompts: companyPromptsWithNames
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (promptSourceError) {
|
} catch (promptSourceError) {
|
||||||
console.error("⚠️ Error getting prompt sources:", promptSourceError);
|
console.error("⚠️ Error getting prompt sources:", promptSourceError);
|
||||||
// Don't fail the entire validation if just prompt sources retrieval fails
|
// Don't fail the entire validation if just prompt sources retrieval fails
|
||||||
@@ -1126,16 +1294,26 @@ router.post("/validate", async (req, res) => {
|
|||||||
// Include prompt sources in the response
|
// Include prompt sources in the response
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
changeDetails: changeDetails,
|
...aiResponse,
|
||||||
performanceMetrics: performanceMetrics || {
|
changeDetails,
|
||||||
|
performanceMetrics:
|
||||||
|
performanceMetrics || {
|
||||||
// Fallback: calculate a simple estimate
|
// Fallback: calculate a simple estimate
|
||||||
promptLength: promptLength,
|
promptLength,
|
||||||
processingTimeSeconds: Math.max(15, Math.round(promptLength / 1000)),
|
processingTimeSeconds: Math.max(15, Math.round(promptLength / 1000)),
|
||||||
isEstimate: true,
|
isEstimate: true,
|
||||||
productCount: products.length
|
productCount: products.length,
|
||||||
|
model: responseModel,
|
||||||
|
tokenUsage: tokenUsageSummary,
|
||||||
|
reasoningTokens: tokenUsageSummary.reasoning,
|
||||||
|
reasoningEffort: reasoningEffortApplied,
|
||||||
|
verbosity: verbosityApplied,
|
||||||
},
|
},
|
||||||
promptSources: promptSources,
|
promptSources,
|
||||||
...aiResponse,
|
model: responseModel,
|
||||||
|
tokenUsage: tokenUsageSummary,
|
||||||
|
reasoningEffort: reasoningEffortApplied,
|
||||||
|
verbosity: verbosityApplied,
|
||||||
});
|
});
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.error("❌ Error parsing AI response:", parseError);
|
console.error("❌ Error parsing AI response:", parseError);
|
||||||
@@ -1151,10 +1329,6 @@ router.post("/validate", async (req, res) => {
|
|||||||
success: false,
|
success: false,
|
||||||
error: "OpenAI API Error: " + openaiError.message,
|
error: "OpenAI API Error: " + openaiError.message,
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
// Clean up database connection and SSH tunnel
|
|
||||||
if (connection) await connection.end();
|
|
||||||
if (ssh) ssh.end();
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ AI Validation Error:", error);
|
console.error("❌ AI Validation Error:", error);
|
||||||
@@ -1167,6 +1341,12 @@ router.post("/validate", async (req, res) => {
|
|||||||
success: false,
|
success: false,
|
||||||
error: error.message || "Error during AI validation",
|
error: error.message || "Error during AI validation",
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
await closeAllConnections();
|
||||||
|
} catch (closeError) {
|
||||||
|
console.error("⚠️ Failed to close DB connections after validation request:", closeError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1249,8 +1429,11 @@ router.get("/test-taxonomy", async (req, res) => {
|
|||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString()
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
if (connection) await connection.end();
|
try {
|
||||||
if (ssh) ssh.end();
|
await closeAllConnections();
|
||||||
|
} catch (closeError) {
|
||||||
|
console.error("⚠️ Failed to close DB connections after test-taxonomy request:", closeError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Test taxonomy endpoint error:", error);
|
console.error("Test taxonomy endpoint error:", error);
|
||||||
@@ -1262,3 +1445,99 @@ router.get("/test-taxonomy", async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
function extractResponseText(response) {
|
||||||
|
if (!response) return "";
|
||||||
|
|
||||||
|
const outputs = [];
|
||||||
|
if (Array.isArray(response.output)) {
|
||||||
|
outputs.push(...response.output);
|
||||||
|
}
|
||||||
|
if (Array.isArray(response.outputs)) {
|
||||||
|
outputs.push(...response.outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const segments = outputs.flatMap((output) => collectTextSegments(output?.content ?? output));
|
||||||
|
|
||||||
|
if (segments.length === 0 && typeof response.output_text === "string") {
|
||||||
|
segments.push(response.output_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segments.length === 0 && response.choices?.length) {
|
||||||
|
segments.push(
|
||||||
|
...collectTextSegments(response.choices?.[0]?.message?.content)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = segments.join("").trim();
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectTextSegments(node) {
|
||||||
|
if (node == null) return [];
|
||||||
|
|
||||||
|
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean") {
|
||||||
|
return [String(node)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(node)) {
|
||||||
|
return node.flatMap(collectTextSegments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof node !== "object") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const segments = [];
|
||||||
|
|
||||||
|
if (typeof node.text === "string") {
|
||||||
|
segments.push(node.text);
|
||||||
|
} else if (Array.isArray(node.text)) {
|
||||||
|
segments.push(...node.text.flatMap(collectTextSegments));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof node.content === "string") {
|
||||||
|
segments.push(node.content);
|
||||||
|
} else if (Array.isArray(node.content)) {
|
||||||
|
segments.push(...node.content.flatMap(collectTextSegments));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof node.output_text === "string") {
|
||||||
|
segments.push(node.output_text);
|
||||||
|
} else if (Array.isArray(node.output_text)) {
|
||||||
|
segments.push(...node.output_text.flatMap(collectTextSegments));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof node.value === "string") {
|
||||||
|
segments.push(node.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof node.data === "string") {
|
||||||
|
segments.push(node.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeJsonResponse(text) {
|
||||||
|
if (!text || typeof text !== 'string') return text;
|
||||||
|
let cleaned = text.trim();
|
||||||
|
|
||||||
|
if (cleaned.startsWith('```')) {
|
||||||
|
const firstLineBreak = cleaned.indexOf('\n');
|
||||||
|
if (firstLineBreak !== -1) {
|
||||||
|
cleaned = cleaned.substring(firstLineBreak + 1);
|
||||||
|
} else {
|
||||||
|
cleaned = cleaned.replace(/^```/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const closingFenceIndex = cleaned.lastIndexOf('```');
|
||||||
|
if (closingFenceIndex !== -1) {
|
||||||
|
cleaned = cleaned.substring(0, closingFenceIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleaned = cleaned.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleaned;
|
||||||
|
}
|
||||||
|
|||||||
493
inventory/package-lock.json
generated
493
inventory/package-lock.json
generated
@@ -1043,9 +1043,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.4.1",
|
"version": "4.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
|
||||||
"integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
|
"integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1085,9 +1085,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-array": {
|
"node_modules/@eslint/config-array": {
|
||||||
"version": "0.19.2",
|
"version": "0.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
|
||||||
"integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
|
"integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1099,10 +1099,20 @@
|
|||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@eslint/config-helpers": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@eslint/core": {
|
"node_modules/@eslint/core": {
|
||||||
"version": "0.11.0",
|
"version": "0.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
|
||||||
"integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==",
|
"integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1113,9 +1123,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc": {
|
"node_modules/@eslint/eslintrc": {
|
||||||
"version": "3.2.0",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
|
||||||
"integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==",
|
"integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1150,13 +1160,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.20.0",
|
"version": "9.36.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz",
|
||||||
"integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==",
|
"integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://eslint.org/donate"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/object-schema": {
|
"node_modules/@eslint/object-schema": {
|
||||||
@@ -1170,32 +1183,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/plugin-kit": {
|
"node_modules/@eslint/plugin-kit": {
|
||||||
"version": "0.2.5",
|
"version": "0.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
|
||||||
"integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
|
"integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/core": "^0.10.0",
|
"@eslint/core": "^0.15.2",
|
||||||
"levn": "^0.4.1"
|
"levn": "^0.4.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
|
|
||||||
"version": "0.10.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz",
|
|
||||||
"integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/json-schema": "^7.0.15"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@floating-ui/core": {
|
"node_modules/@floating-ui/core": {
|
||||||
"version": "1.6.9",
|
"version": "1.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
|
||||||
@@ -1296,9 +1296,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/retry": {
|
"node_modules/@humanwhocodes/retry": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
|
||||||
"integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
|
"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2559,9 +2559,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.3.tgz",
|
||||||
"integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==",
|
"integrity": "sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -2573,9 +2573,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.3.tgz",
|
||||||
"integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==",
|
"integrity": "sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2587,9 +2587,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.3.tgz",
|
||||||
"integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==",
|
"integrity": "sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2601,9 +2601,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.3.tgz",
|
||||||
"integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==",
|
"integrity": "sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2615,9 +2615,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.3.tgz",
|
||||||
"integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==",
|
"integrity": "sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2629,9 +2629,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.3.tgz",
|
||||||
"integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==",
|
"integrity": "sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2643,9 +2643,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.3.tgz",
|
||||||
"integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==",
|
"integrity": "sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -2657,9 +2657,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.3.tgz",
|
||||||
"integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==",
|
"integrity": "sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -2671,9 +2671,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.3.tgz",
|
||||||
"integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==",
|
"integrity": "sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2685,9 +2685,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.3.tgz",
|
||||||
"integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==",
|
"integrity": "sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2698,10 +2698,10 @@
|
|||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.3.tgz",
|
||||||
"integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==",
|
"integrity": "sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -2712,10 +2712,10 @@
|
|||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.3.tgz",
|
||||||
"integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==",
|
"integrity": "sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -2727,9 +2727,23 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.3.tgz",
|
||||||
"integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==",
|
"integrity": "sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||||
|
"version": "4.52.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.3.tgz",
|
||||||
|
"integrity": "sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -2741,9 +2755,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.3.tgz",
|
||||||
"integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==",
|
"integrity": "sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -2755,9 +2769,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.3.tgz",
|
||||||
"integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==",
|
"integrity": "sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2769,9 +2783,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.3.tgz",
|
||||||
"integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==",
|
"integrity": "sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2782,10 +2796,24 @@
|
|||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||||
|
"version": "4.52.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.3.tgz",
|
||||||
|
"integrity": "sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openharmony"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.3.tgz",
|
||||||
"integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==",
|
"integrity": "sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2797,9 +2825,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.3.tgz",
|
||||||
"integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==",
|
"integrity": "sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -2810,10 +2838,24 @@
|
|||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||||
|
"version": "4.52.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.3.tgz",
|
||||||
|
"integrity": "sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.3.tgz",
|
||||||
"integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==",
|
"integrity": "sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -3000,12 +3042,6 @@
|
|||||||
"@babel/types": "^7.20.7"
|
"@babel/types": "^7.20.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/cookie": {
|
|
||||||
"version": "0.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
|
||||||
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-array": {
|
"node_modules/@types/d3-array": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
|
||||||
@@ -3070,9 +3106,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -3306,9 +3342,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -3407,9 +3443,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.14.0",
|
"version": "8.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -3577,13 +3613,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.8.3",
|
"version": "1.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
||||||
"integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==",
|
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.4",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3652,9 +3688,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4873,22 +4909,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.20.1",
|
"version": "9.36.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz",
|
||||||
"integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==",
|
"integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
"@eslint/config-array": "^0.19.0",
|
"@eslint/config-array": "^0.21.0",
|
||||||
"@eslint/core": "^0.11.0",
|
"@eslint/config-helpers": "^0.3.1",
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/core": "^0.15.2",
|
||||||
"@eslint/js": "9.20.0",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@eslint/plugin-kit": "^0.2.5",
|
"@eslint/js": "9.36.0",
|
||||||
|
"@eslint/plugin-kit": "^0.3.5",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@humanwhocodes/retry": "^0.4.1",
|
"@humanwhocodes/retry": "^0.4.2",
|
||||||
"@types/estree": "^1.0.6",
|
"@types/estree": "^1.0.6",
|
||||||
"@types/json-schema": "^7.0.15",
|
"@types/json-schema": "^7.0.15",
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.12.4",
|
||||||
@@ -4896,9 +4933,9 @@
|
|||||||
"cross-spawn": "^7.0.6",
|
"cross-spawn": "^7.0.6",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"eslint-scope": "^8.2.0",
|
"eslint-scope": "^8.4.0",
|
||||||
"eslint-visitor-keys": "^4.2.0",
|
"eslint-visitor-keys": "^4.2.1",
|
||||||
"espree": "^10.3.0",
|
"espree": "^10.4.0",
|
||||||
"esquery": "^1.5.0",
|
"esquery": "^1.5.0",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
@@ -4956,9 +4993,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-scope": {
|
"node_modules/eslint-scope": {
|
||||||
"version": "8.2.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
||||||
"integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
|
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4973,9 +5010,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-visitor-keys": {
|
"node_modules/eslint-visitor-keys": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
||||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -5019,15 +5056,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/espree": {
|
"node_modules/espree": {
|
||||||
"version": "10.3.0",
|
"version": "10.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
|
||||||
"integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
|
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "^8.14.0",
|
"acorn": "^8.15.0",
|
||||||
"acorn-jsx": "^5.3.2",
|
"acorn-jsx": "^5.3.2",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -5331,14 +5368,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.12"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -5545,9 +5583,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob/node_modules/brace-expansion": {
|
"node_modules/glob/node_modules/brace-expansion": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
@@ -7080,15 +7118,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "7.1.5",
|
"version": "7.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.3.tgz",
|
||||||
"integrity": "sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==",
|
"integrity": "sha512-4o2iWCFIwhI/eYAIL43+cjORXYn/aRQPgtFRRZb3VzoyQ5Uej0Bmqj7437L97N9NJW4wnicSwLOLS+yCXfAPgg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/cookie": "^0.6.0",
|
|
||||||
"cookie": "^1.0.1",
|
"cookie": "^1.0.1",
|
||||||
"set-cookie-parser": "^2.6.0",
|
"set-cookie-parser": "^2.6.0"
|
||||||
"turbo-stream": "2.4.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
@@ -7104,12 +7140,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "7.1.5",
|
"version": "7.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.3.tgz",
|
||||||
"integrity": "sha512-/4f9+up0Qv92D3bB8iN5P1s3oHAepSGa9h5k6tpTFlixTTskJZwKGhJ6vRJ277tLD1zuaZTt95hyGWV1Z37csQ==",
|
"integrity": "sha512-1QSbA0TGGFKTAc/aWjpfW/zoEukYfU4dc1dLkT/vvf54JoGMkW+fNA+3oyo2gWVW1GM7BxjJVHz5GnPJv40rvg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-router": "7.1.5"
|
"react-router": "7.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
@@ -7331,13 +7367,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.34.8",
|
"version": "4.52.3",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.3.tgz",
|
||||||
"integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
|
"integrity": "sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.6"
|
"@types/estree": "1.0.8"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"rollup": "dist/bin/rollup"
|
"rollup": "dist/bin/rollup"
|
||||||
@@ -7347,25 +7383,28 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.34.8",
|
"@rollup/rollup-android-arm-eabi": "4.52.3",
|
||||||
"@rollup/rollup-android-arm64": "4.34.8",
|
"@rollup/rollup-android-arm64": "4.52.3",
|
||||||
"@rollup/rollup-darwin-arm64": "4.34.8",
|
"@rollup/rollup-darwin-arm64": "4.52.3",
|
||||||
"@rollup/rollup-darwin-x64": "4.34.8",
|
"@rollup/rollup-darwin-x64": "4.52.3",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.34.8",
|
"@rollup/rollup-freebsd-arm64": "4.52.3",
|
||||||
"@rollup/rollup-freebsd-x64": "4.34.8",
|
"@rollup/rollup-freebsd-x64": "4.52.3",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.34.8",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.52.3",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.34.8",
|
"@rollup/rollup-linux-arm-musleabihf": "4.52.3",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.34.8",
|
"@rollup/rollup-linux-arm64-gnu": "4.52.3",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.34.8",
|
"@rollup/rollup-linux-arm64-musl": "4.52.3",
|
||||||
"@rollup/rollup-linux-loongarch64-gnu": "4.34.8",
|
"@rollup/rollup-linux-loong64-gnu": "4.52.3",
|
||||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.8",
|
"@rollup/rollup-linux-ppc64-gnu": "4.52.3",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.34.8",
|
"@rollup/rollup-linux-riscv64-gnu": "4.52.3",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.34.8",
|
"@rollup/rollup-linux-riscv64-musl": "4.52.3",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.34.8",
|
"@rollup/rollup-linux-s390x-gnu": "4.52.3",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.34.8",
|
"@rollup/rollup-linux-x64-gnu": "4.52.3",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.34.8",
|
"@rollup/rollup-linux-x64-musl": "4.52.3",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.34.8",
|
"@rollup/rollup-openharmony-arm64": "4.52.3",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.34.8",
|
"@rollup/rollup-win32-arm64-msvc": "4.52.3",
|
||||||
|
"@rollup/rollup-win32-ia32-msvc": "4.52.3",
|
||||||
|
"@rollup/rollup-win32-x64-gnu": "4.52.3",
|
||||||
|
"@rollup/rollup-win32-x64-msvc": "4.52.3",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -7806,6 +7845,54 @@
|
|||||||
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
|
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/tinyglobby": {
|
||||||
|
"version": "0.2.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
|
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"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,
|
||||||
|
"license": "MIT",
|
||||||
|
"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,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
@@ -7843,12 +7930,6 @@
|
|||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
"node_modules/turbo-stream": {
|
|
||||||
"version": "2.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
|
||||||
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@@ -8054,15 +8135,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.2.2",
|
"version": "6.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz",
|
||||||
"integrity": "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==",
|
"integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
|
"fdir": "^6.4.4",
|
||||||
|
"picomatch": "^4.0.2",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"rollup": "^4.30.1"
|
"rollup": "^4.34.9",
|
||||||
|
"tinyglobby": "^0.2.13"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"vite": "bin/vite.js"
|
"vite": "bin/vite.js"
|
||||||
@@ -8125,6 +8209,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vite/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,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"picomatch": "^3 || ^4"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"picomatch": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vite/node_modules/picomatch": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wcwidth": {
|
"node_modules/wcwidth": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
} from "../hooks/useAiValidation";
|
} from "../hooks/useAiValidation";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Protected } from "@/components/auth/Protected";
|
||||||
|
|
||||||
interface TaxonomyStats {
|
interface TaxonomyStats {
|
||||||
categories: number;
|
categories: number;
|
||||||
@@ -96,7 +97,7 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
|
|||||||
getFieldDisplayValueWithHighlight,
|
getFieldDisplayValueWithHighlight,
|
||||||
fields,
|
fields,
|
||||||
}) => {
|
}) => {
|
||||||
const [costPerMillionTokens, setCostPerMillionTokens] = useState(2.5); // Default cost
|
const [costPerMillionTokens, setCostPerMillionTokens] = useState(1.25); // Default cost
|
||||||
|
|
||||||
// Create our own state to track changes
|
// Create our own state to track changes
|
||||||
const [localReversionState, setLocalReversionState] = useState<
|
const [localReversionState, setLocalReversionState] = useState<
|
||||||
@@ -170,8 +171,20 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
|
|||||||
return (estimatedTokens / 1_000_000) * costPerMillionTokens * 100; // In cents
|
return (estimatedTokens / 1_000_000) * costPerMillionTokens * 100; // In cents
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatNumber = (value: number | null | undefined): string => {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return "—";
|
||||||
|
}
|
||||||
|
return value.toLocaleString();
|
||||||
|
};
|
||||||
|
|
||||||
// Use the prompt length from the current prompt
|
// Use the prompt length from the current prompt
|
||||||
const promptLength = currentPrompt.prompt ? currentPrompt.prompt.length : 0;
|
const promptLength = currentPrompt.prompt ? currentPrompt.prompt.length : 0;
|
||||||
|
const tokenUsage = aiValidationDetails.tokenUsage;
|
||||||
|
const formattedReasoningEffort = aiValidationDetails.reasoningEffort
|
||||||
|
? aiValidationDetails.reasoningEffort.charAt(0).toUpperCase() +
|
||||||
|
aiValidationDetails.reasoningEffort.slice(1)
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -677,30 +690,29 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
|
|||||||
aiValidationProgress.estimatedSeconds &&
|
aiValidationProgress.estimatedSeconds &&
|
||||||
aiValidationProgress.elapsedSeconds !== undefined &&
|
aiValidationProgress.elapsedSeconds !== undefined &&
|
||||||
aiValidationProgress.step > 0 &&
|
aiValidationProgress.step > 0 &&
|
||||||
aiValidationProgress.step < 5 && (
|
aiValidationProgress.step < 5 && (() => {
|
||||||
<div className="text-center text-sm">
|
const elapsedSeconds = aiValidationProgress.elapsedSeconds;
|
||||||
{(() => {
|
const totalEstimatedSeconds = aiValidationProgress.estimatedSeconds;
|
||||||
// Calculate time remaining using the elapsed seconds
|
|
||||||
const elapsedSeconds =
|
|
||||||
aiValidationProgress.elapsedSeconds;
|
|
||||||
const totalEstimatedSeconds =
|
|
||||||
aiValidationProgress.estimatedSeconds;
|
|
||||||
const remainingSeconds = Math.max(
|
const remainingSeconds = Math.max(
|
||||||
0,
|
0,
|
||||||
totalEstimatedSeconds - elapsedSeconds
|
totalEstimatedSeconds - elapsedSeconds
|
||||||
);
|
);
|
||||||
|
|
||||||
// Format time remaining
|
if (remainingSeconds <= 5) {
|
||||||
if (remainingSeconds < 60) {
|
return null;
|
||||||
return `Approximately ${Math.round(
|
}
|
||||||
remainingSeconds
|
|
||||||
)} seconds remaining`;
|
const message = remainingSeconds < 60
|
||||||
} else {
|
? `Approximately ${Math.round(remainingSeconds)} seconds remaining`
|
||||||
|
: (() => {
|
||||||
const minutes = Math.floor(remainingSeconds / 60);
|
const minutes = Math.floor(remainingSeconds / 60);
|
||||||
const seconds = Math.round(remainingSeconds % 60);
|
const seconds = Math.round(remainingSeconds % 60);
|
||||||
return `Approximately ${minutes}m ${seconds}s remaining`;
|
return `Approximately ${minutes}m ${seconds}s remaining`;
|
||||||
}
|
})();
|
||||||
})()}
|
|
||||||
|
return (
|
||||||
|
<div className="text-center text-sm">
|
||||||
|
{message}
|
||||||
{aiValidationProgress.promptLength && (
|
{aiValidationProgress.promptLength && (
|
||||||
<p className="mt-1 text-xs text-muted-foreground">
|
<p className="mt-1 text-xs text-muted-foreground">
|
||||||
Prompt length:{" "}
|
Prompt length:{" "}
|
||||||
@@ -709,7 +721,8 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
|
})()
|
||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
@@ -723,13 +736,139 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
|
|||||||
setAiValidationDetails((prev) => ({ ...prev, isOpen: open }))
|
setAiValidationDetails((prev) => ({ ...prev, isOpen: open }))
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<DialogContent className="max-w-6xl w-[90vw]">
|
<DialogContent className="max-w-6xl w-[90vw] max-h-[90vh] overflow-auto">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>AI Validation Results</DialogTitle>
|
<DialogTitle>AI Validation Results</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Review the changes and warnings suggested by the AI
|
Review the changes and warnings suggested by the AI
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
<Protected permission="admin:debug">
|
||||||
|
{(aiValidationDetails.model || tokenUsage || formattedReasoningEffort) && (
|
||||||
|
<div className="mb-4 rounded-md border bg-muted/40 p-4 text-sm">
|
||||||
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
|
{aiValidationDetails.model && (
|
||||||
|
<Badge variant="outline">
|
||||||
|
Model · {aiValidationDetails.model}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
{formattedReasoningEffort && (
|
||||||
|
<Badge variant="secondary">
|
||||||
|
Reasoning {formattedReasoningEffort}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{tokenUsage && (
|
||||||
|
<div className="mt-3 grid gap-4 text-xs sm:grid-cols-2 lg:grid-cols-5">
|
||||||
|
<div>
|
||||||
|
<span className="block text-muted-foreground">
|
||||||
|
Prompt tokens
|
||||||
|
</span>
|
||||||
|
<span className="font-medium">
|
||||||
|
{formatNumber(tokenUsage.prompt)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="block text-muted-foreground">
|
||||||
|
Completion tokens
|
||||||
|
</span>
|
||||||
|
<span className="font-medium">
|
||||||
|
{formatNumber(tokenUsage.completion)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="block text-muted-foreground">
|
||||||
|
Total tokens
|
||||||
|
</span>
|
||||||
|
<span className="font-medium">
|
||||||
|
{formatNumber(tokenUsage.total)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="block text-muted-foreground">
|
||||||
|
Reasoning tokens
|
||||||
|
</span>
|
||||||
|
<span className="font-medium">
|
||||||
|
{formatNumber(tokenUsage.reasoning)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="block text-muted-foreground">
|
||||||
|
Cached prompt tokens
|
||||||
|
</span>
|
||||||
|
<span className="font-medium">
|
||||||
|
{formatNumber(tokenUsage.cachedPrompt)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Protected>
|
||||||
|
{(aiValidationDetails.summary ||
|
||||||
|
(aiValidationDetails.changes && aiValidationDetails.changes.length > 0) ||
|
||||||
|
(aiValidationDetails.warnings && aiValidationDetails.warnings.length > 0) ||
|
||||||
|
(aiValidationDetails.qualityNotes && aiValidationDetails.qualityNotes.length > 0) ||
|
||||||
|
(aiValidationDetails.nextSteps && aiValidationDetails.nextSteps.length > 0)) && (
|
||||||
|
<Card className="mb-4 max-h-[25vh] overflow-auto">
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-base">Overall Assessment</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-3 text-sm text-muted-foreground">
|
||||||
|
{aiValidationDetails.changes &&
|
||||||
|
aiValidationDetails.changes.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<h4 className="font-medium text-foreground mb-1">
|
||||||
|
Key Changes
|
||||||
|
</h4>
|
||||||
|
<ul className="list-disc pl-5 space-y-1">
|
||||||
|
{aiValidationDetails.changes.map((change, idx) => (
|
||||||
|
<li key={`change-${idx}`}>{change}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{aiValidationDetails.warnings &&
|
||||||
|
aiValidationDetails.warnings.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<h4 className="font-medium text-foreground mb-1">
|
||||||
|
Warnings
|
||||||
|
</h4>
|
||||||
|
<ul className="list-disc pl-5 space-y-1">
|
||||||
|
{aiValidationDetails.warnings.map((warning, idx) => (
|
||||||
|
<li key={`warning-${idx}`}>{warning}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{aiValidationDetails.summary && (
|
||||||
|
<p className="leading-relaxed">{aiValidationDetails.summary}</p>
|
||||||
|
)}
|
||||||
|
{aiValidationDetails.qualityNotes &&
|
||||||
|
aiValidationDetails.qualityNotes.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<h4 className="font-medium text-foreground mb-1">Quality Notes</h4>
|
||||||
|
<ul className="list-disc pl-5 space-y-1">
|
||||||
|
{aiValidationDetails.qualityNotes.map((note, idx) => (
|
||||||
|
<li key={`quality-note-${idx}`}>{note}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{aiValidationDetails.nextSteps &&
|
||||||
|
aiValidationDetails.nextSteps.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<h4 className="font-medium text-foreground mb-1">Suggested Next Steps</h4>
|
||||||
|
<ul className="list-disc pl-5 space-y-1">
|
||||||
|
{aiValidationDetails.nextSteps.map((step, idx) => (
|
||||||
|
<li key={`next-step-${idx}`}>{step}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
<ScrollArea className="max-h-[70vh]">
|
<ScrollArea className="max-h-[70vh]">
|
||||||
{aiValidationDetails.changeDetails &&
|
{aiValidationDetails.changeDetails &&
|
||||||
aiValidationDetails.changeDetails.length > 0 ? (
|
aiValidationDetails.changeDetails.length > 0 ? (
|
||||||
@@ -855,23 +994,7 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="py-8 text-center text-muted-foreground">
|
<div className="py-8 text-center text-muted-foreground">
|
||||||
{aiValidationDetails.warnings &&
|
<p>No field-level changes were suggested by the AI.</p>
|
||||||
aiValidationDetails.warnings.length > 0 ? (
|
|
||||||
<div>
|
|
||||||
<p className="mb-4">
|
|
||||||
No changes were made, but the AI provided some warnings:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc pl-8 text-left">
|
|
||||||
{aiValidationDetails.warnings.map((warning, i) => (
|
|
||||||
<li key={`warning-${i}`} className="mb-2">
|
|
||||||
{warning}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p>No changes or warnings were suggested by the AI.</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -20,12 +20,28 @@ export interface ProductChangeDetail {
|
|||||||
changes: ChangeDetail[];
|
changes: ChangeDetail[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ReasoningEffortLevel = 'minimal' | 'low' | 'medium' | 'high';
|
||||||
|
|
||||||
|
export interface AiValidationTokenUsage {
|
||||||
|
prompt: number | null;
|
||||||
|
completion: number | null;
|
||||||
|
total: number | null;
|
||||||
|
reasoning?: number | null;
|
||||||
|
cachedPrompt?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface AiValidationDetails {
|
export interface AiValidationDetails {
|
||||||
changes: string[];
|
changes: string[];
|
||||||
warnings: string[];
|
warnings: string[];
|
||||||
changeDetails: ProductChangeDetail[];
|
changeDetails: ProductChangeDetail[];
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
originalData?: RowData<string>[];
|
originalData?: RowData<any>[];
|
||||||
|
model?: string;
|
||||||
|
reasoningEffort?: ReasoningEffortLevel;
|
||||||
|
tokenUsage?: AiValidationTokenUsage;
|
||||||
|
summary?: string;
|
||||||
|
qualityNotes?: string[];
|
||||||
|
nextSteps?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AiValidationProgress {
|
export interface AiValidationProgress {
|
||||||
@@ -37,8 +53,119 @@ export interface AiValidationProgress {
|
|||||||
promptLength?: number;
|
promptLength?: number;
|
||||||
elapsedSeconds?: number;
|
elapsedSeconds?: number;
|
||||||
progressPercent?: number;
|
progressPercent?: number;
|
||||||
|
model?: string;
|
||||||
|
reasoningEffort?: ReasoningEffortLevel;
|
||||||
|
tokenUsage?: AiValidationTokenUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toNumberOrNull = (value: unknown): number | null => {
|
||||||
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const parsed = Number(value);
|
||||||
|
return Number.isFinite(parsed) ? parsed : null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizeReasoningEffort = (
|
||||||
|
value: unknown
|
||||||
|
): ReasoningEffortLevel | undefined => {
|
||||||
|
if (typeof value !== 'string') return undefined;
|
||||||
|
const normalized = value.toLowerCase();
|
||||||
|
if (
|
||||||
|
normalized === 'minimal' ||
|
||||||
|
normalized === 'low' ||
|
||||||
|
normalized === 'medium' ||
|
||||||
|
normalized === 'high'
|
||||||
|
) {
|
||||||
|
return normalized as ReasoningEffortLevel;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isRecord = (value: unknown): value is Record<string, any> => {
|
||||||
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const valuesAreEqual = (a: unknown, b: unknown): boolean => {
|
||||||
|
if (a === b) {
|
||||||
|
// Handle NaN equality manually
|
||||||
|
return a === a || b === b;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.stringify(a) === JSON.stringify(b);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildChangeDetailsFromData = <T extends string>(
|
||||||
|
originalRows: RowData<T>[],
|
||||||
|
correctedRows: unknown[]
|
||||||
|
): ProductChangeDetail[] => {
|
||||||
|
if (!Array.isArray(correctedRows)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const details: ProductChangeDetail[] = [];
|
||||||
|
const maxLength = Math.max(originalRows.length, correctedRows.length);
|
||||||
|
|
||||||
|
for (let index = 0; index < maxLength; index++) {
|
||||||
|
const original = (originalRows[index] as Record<string, any> | undefined) ?? undefined;
|
||||||
|
const correctedCandidate = correctedRows[index];
|
||||||
|
|
||||||
|
if (!isRecord(correctedCandidate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = new Set<string>([
|
||||||
|
...Object.keys(original ?? {}),
|
||||||
|
...Object.keys(correctedCandidate),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const changes: ChangeDetail[] = [];
|
||||||
|
|
||||||
|
keys.forEach((key) => {
|
||||||
|
if (key.startsWith('__')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalValue = original ? original[key] : undefined;
|
||||||
|
const correctedValue = correctedCandidate[key];
|
||||||
|
|
||||||
|
if (!valuesAreEqual(originalValue, correctedValue)) {
|
||||||
|
changes.push({
|
||||||
|
field: key,
|
||||||
|
original: originalValue,
|
||||||
|
corrected: correctedValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changes.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const titleCandidate =
|
||||||
|
(original && (original.name ?? original.title)) ??
|
||||||
|
(correctedCandidate.name ?? correctedCandidate.title);
|
||||||
|
|
||||||
|
details.push({
|
||||||
|
productIndex: index,
|
||||||
|
title:
|
||||||
|
typeof titleCandidate === 'string'
|
||||||
|
? titleCandidate
|
||||||
|
: `Product ${index + 1}`,
|
||||||
|
changes,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return details;
|
||||||
|
};
|
||||||
|
|
||||||
export interface CurrentPrompt {
|
export interface CurrentPrompt {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
prompt: string | null;
|
prompt: string | null;
|
||||||
@@ -374,6 +501,9 @@ export const useAiValidation = <T extends string>(
|
|||||||
startTime,
|
startTime,
|
||||||
elapsedSeconds: 0,
|
elapsedSeconds: 0,
|
||||||
progressPercent: 0,
|
progressPercent: 0,
|
||||||
|
model: undefined,
|
||||||
|
reasoningEffort: undefined,
|
||||||
|
tokenUsage: undefined,
|
||||||
...(aiValidationProgress.estimatedSeconds ? {
|
...(aiValidationProgress.estimatedSeconds ? {
|
||||||
estimatedSeconds: aiValidationProgress.estimatedSeconds,
|
estimatedSeconds: aiValidationProgress.estimatedSeconds,
|
||||||
promptLength: aiValidationProgress.promptLength
|
promptLength: aiValidationProgress.promptLength
|
||||||
@@ -476,14 +606,25 @@ export const useAiValidation = <T extends string>(
|
|||||||
promptLength: prev.promptLength
|
promptLength: prev.promptLength
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const response = await fetch(`${getApiUrl()}/ai-validation/validate`, {
|
const requestBody = JSON.stringify({ products: cleanedData });
|
||||||
|
const fetchPromise = fetch(`${getApiUrl()}/ai-validation/validate`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ products: cleanedData }),
|
body: requestBody,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setAiValidationProgress(prev => ({
|
||||||
|
...prev,
|
||||||
|
status: "Waiting on AI response...",
|
||||||
|
step: Math.max(prev.step, 2),
|
||||||
|
estimatedSeconds: prev.estimatedSeconds,
|
||||||
|
promptLength: prev.promptLength
|
||||||
|
}));
|
||||||
|
|
||||||
|
const response = await fetchPromise;
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorText = await response.text();
|
const errorText = await response.text();
|
||||||
console.error('AI validation error response:', {
|
console.error('AI validation error response:', {
|
||||||
@@ -501,6 +642,111 @@ export const useAiValidation = <T extends string>(
|
|||||||
throw new Error(result.error || 'AI validation failed');
|
throw new Error(result.error || 'AI validation failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const usageSource: any =
|
||||||
|
result.tokenUsage ||
|
||||||
|
result.performanceMetrics?.tokenUsage ||
|
||||||
|
result.usage;
|
||||||
|
const modelUsed: string | undefined =
|
||||||
|
typeof result.model === 'string'
|
||||||
|
? result.model
|
||||||
|
: typeof result.modelName === 'string'
|
||||||
|
? result.modelName
|
||||||
|
: typeof result.modelId === 'string'
|
||||||
|
? result.modelId
|
||||||
|
: typeof result.performanceMetrics?.model === 'string'
|
||||||
|
? result.performanceMetrics.model
|
||||||
|
: undefined;
|
||||||
|
const reasoningEffort = normalizeReasoningEffort(
|
||||||
|
result.reasoningEffort ||
|
||||||
|
result.reasoning_effort ||
|
||||||
|
result.performanceMetrics?.reasoningEffort
|
||||||
|
);
|
||||||
|
|
||||||
|
let normalizedTokenUsage: AiValidationTokenUsage | undefined;
|
||||||
|
if (usageSource) {
|
||||||
|
const promptTokensRaw =
|
||||||
|
usageSource.prompt ??
|
||||||
|
usageSource.promptTokens ??
|
||||||
|
usageSource.prompt_tokens ??
|
||||||
|
usageSource.input;
|
||||||
|
const completionTokensRaw =
|
||||||
|
usageSource.completion ??
|
||||||
|
usageSource.completionTokens ??
|
||||||
|
usageSource.completion_tokens ??
|
||||||
|
usageSource.output;
|
||||||
|
const totalTokensRaw =
|
||||||
|
usageSource.total ??
|
||||||
|
usageSource.totalTokens ??
|
||||||
|
usageSource.total_tokens ??
|
||||||
|
usageSource.tokenTotal;
|
||||||
|
const reasoningTokensRaw =
|
||||||
|
usageSource.reasoning ??
|
||||||
|
usageSource.reasoningTokens ??
|
||||||
|
usageSource.reasoning_tokens;
|
||||||
|
const cachedPromptRaw =
|
||||||
|
usageSource.cachedPrompt ??
|
||||||
|
usageSource.cachedTokens ??
|
||||||
|
usageSource.cached_prompt ??
|
||||||
|
usageSource.cached_tokens ??
|
||||||
|
usageSource.cached;
|
||||||
|
|
||||||
|
const promptTokens = toNumberOrNull(promptTokensRaw);
|
||||||
|
const completionTokens = toNumberOrNull(completionTokensRaw);
|
||||||
|
let totalTokens = toNumberOrNull(totalTokensRaw);
|
||||||
|
if (
|
||||||
|
totalTokens === null &&
|
||||||
|
promptTokens !== null &&
|
||||||
|
completionTokens !== null
|
||||||
|
) {
|
||||||
|
totalTokens = promptTokens + completionTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reasoningTokens = toNumberOrNull(reasoningTokensRaw);
|
||||||
|
const cachedPrompt = toNumberOrNull(cachedPromptRaw);
|
||||||
|
|
||||||
|
if (
|
||||||
|
promptTokens !== null ||
|
||||||
|
completionTokens !== null ||
|
||||||
|
totalTokens !== null ||
|
||||||
|
reasoningTokens !== null ||
|
||||||
|
cachedPrompt !== null
|
||||||
|
) {
|
||||||
|
normalizedTokenUsage = {
|
||||||
|
prompt: promptTokens,
|
||||||
|
completion: completionTokens,
|
||||||
|
total: totalTokens,
|
||||||
|
reasoning: reasoningTokens,
|
||||||
|
cachedPrompt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const changesFromResult = Array.isArray(result.changes)
|
||||||
|
? result.changes
|
||||||
|
: [];
|
||||||
|
const warningsFromResult = Array.isArray(result.warnings)
|
||||||
|
? result.warnings
|
||||||
|
: [];
|
||||||
|
const summaryFromResult = typeof result.summary === 'string'
|
||||||
|
? result.summary
|
||||||
|
: typeof result.overallSummary === 'string'
|
||||||
|
? result.overallSummary
|
||||||
|
: '';
|
||||||
|
const qualityNotesFromResult = Array.isArray(result.qualityNotes)
|
||||||
|
? result.qualityNotes
|
||||||
|
: Array.isArray(result.quality_notes)
|
||||||
|
? result.quality_notes
|
||||||
|
: Array.isArray(result.qualitySummary)
|
||||||
|
? result.qualitySummary
|
||||||
|
: [];
|
||||||
|
const nextStepsFromResult = Array.isArray(result.nextSteps)
|
||||||
|
? result.nextSteps
|
||||||
|
: Array.isArray(result.recommendedNextSteps)
|
||||||
|
? result.recommendedNextSteps
|
||||||
|
: Array.isArray(result.followUpActions)
|
||||||
|
? result.followUpActions
|
||||||
|
: [];
|
||||||
|
|
||||||
// Store the prompt sources if they exist
|
// Store the prompt sources if they exist
|
||||||
if (result.promptSources) {
|
if (result.promptSources) {
|
||||||
setCurrentPrompt(prev => {
|
setCurrentPrompt(prev => {
|
||||||
@@ -534,14 +780,23 @@ export const useAiValidation = <T extends string>(
|
|||||||
result.performanceMetrics.processingTimeSeconds ||
|
result.performanceMetrics.processingTimeSeconds ||
|
||||||
prev.estimatedSeconds,
|
prev.estimatedSeconds,
|
||||||
promptLength: result.performanceMetrics.promptLength || prev.promptLength,
|
promptLength: result.performanceMetrics.promptLength || prev.promptLength,
|
||||||
progressPercent: 75 // 75% complete when we're processing the AI response
|
progressPercent: 75, // 75% complete when we're processing the AI response
|
||||||
|
model: modelUsed ?? prev.model,
|
||||||
|
reasoningEffort: reasoningEffort ?? prev.reasoningEffort,
|
||||||
|
tokenUsage:
|
||||||
|
normalizedTokenUsage ??
|
||||||
|
result.performanceMetrics.tokenUsage ??
|
||||||
|
prev.tokenUsage,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
setAiValidationProgress(prev => ({
|
setAiValidationProgress(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
status: "Processing AI response...",
|
status: "Processing AI response...",
|
||||||
step: 3,
|
step: 3,
|
||||||
progressPercent: 75
|
progressPercent: 75,
|
||||||
|
model: modelUsed ?? prev.model,
|
||||||
|
reasoningEffort: reasoningEffort ?? prev.reasoningEffort,
|
||||||
|
tokenUsage: normalizedTokenUsage ?? prev.tokenUsage,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,7 +875,9 @@ export const useAiValidation = <T extends string>(
|
|||||||
console.log('About to update data with AI corrections:', {
|
console.log('About to update data with AI corrections:', {
|
||||||
originalDataSample: data.slice(0, 2),
|
originalDataSample: data.slice(0, 2),
|
||||||
processedDataSample: processedData.slice(0, 2),
|
processedDataSample: processedData.slice(0, 2),
|
||||||
correctionCount: result.changes?.length || 0
|
correctionCount: result.changes?.length || 0,
|
||||||
|
changeDetailCount: 0,
|
||||||
|
changeDetailsPreview: []
|
||||||
});
|
});
|
||||||
|
|
||||||
// First validate the new data to ensure all validation rules are applied
|
// First validate the new data to ensure all validation rules are applied
|
||||||
@@ -644,27 +901,63 @@ export const useAiValidation = <T extends string>(
|
|||||||
hasErrors: false // We no longer check row.__errors
|
hasErrors: false // We no longer check row.__errors
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show changes and warnings in dialog after data is updated
|
const changeDetailsForDialog = buildChangeDetailsFromData(
|
||||||
setAiValidationDetails({
|
originalDataCopy,
|
||||||
changes: result.changes || [],
|
validatedData as RowData<T>[]
|
||||||
warnings: result.warnings || [],
|
);
|
||||||
changeDetails: result.changeDetails || [],
|
|
||||||
isOpen: true,
|
console.log('Computed change details after validation:', {
|
||||||
originalData: originalDataCopy // Use the stored original data
|
changeDetailCount: changeDetailsForDialog.length,
|
||||||
|
changeDetailsPreview: changeDetailsForDialog.slice(0, 2)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const detailPayload: AiValidationDetails = {
|
||||||
|
changes: changesFromResult,
|
||||||
|
warnings: warningsFromResult,
|
||||||
|
changeDetails: changeDetailsForDialog,
|
||||||
|
isOpen: true,
|
||||||
|
originalData: originalDataCopy,
|
||||||
|
model: modelUsed,
|
||||||
|
reasoningEffort,
|
||||||
|
tokenUsage: normalizedTokenUsage,
|
||||||
|
summary: summaryFromResult,
|
||||||
|
qualityNotes: qualityNotesFromResult,
|
||||||
|
nextSteps: nextStepsFromResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show changes and warnings in dialog after data is updated
|
||||||
|
setAiValidationDetails(detailPayload);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error validating AI corrections:', error);
|
console.error('Error validating AI corrections:', error);
|
||||||
// Fall back to basic update without validation
|
// Fall back to basic update without validation
|
||||||
setData(processedData);
|
setData(processedData);
|
||||||
|
|
||||||
// Still show the result dialog even if validation failed
|
const changeDetailsForDialog = buildChangeDetailsFromData(
|
||||||
setAiValidationDetails({
|
originalDataCopy,
|
||||||
changes: result.changes || [],
|
processedData as RowData<T>[]
|
||||||
warnings: result.warnings || [],
|
);
|
||||||
changeDetails: result.changeDetails || [],
|
|
||||||
isOpen: true,
|
console.log('Computed change details after fallback:', {
|
||||||
originalData: originalDataCopy, // Use the stored original data
|
changeDetailCount: changeDetailsForDialog.length,
|
||||||
|
changeDetailsPreview: changeDetailsForDialog.slice(0, 2)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const detailPayload: AiValidationDetails = {
|
||||||
|
changes: changesFromResult,
|
||||||
|
warnings: warningsFromResult,
|
||||||
|
changeDetails: changeDetailsForDialog,
|
||||||
|
isOpen: true,
|
||||||
|
originalData: originalDataCopy,
|
||||||
|
model: modelUsed,
|
||||||
|
reasoningEffort,
|
||||||
|
tokenUsage: normalizedTokenUsage,
|
||||||
|
summary: summaryFromResult,
|
||||||
|
qualityNotes: qualityNotesFromResult,
|
||||||
|
nextSteps: nextStepsFromResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Still show the result dialog even if validation failed
|
||||||
|
setAiValidationDetails(detailPayload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +966,10 @@ export const useAiValidation = <T extends string>(
|
|||||||
status: "Validation complete!",
|
status: "Validation complete!",
|
||||||
step: 5,
|
step: 5,
|
||||||
estimatedSeconds: prev.estimatedSeconds,
|
estimatedSeconds: prev.estimatedSeconds,
|
||||||
promptLength: prev.promptLength
|
promptLength: prev.promptLength,
|
||||||
|
model: modelUsed ?? prev.model,
|
||||||
|
reasoningEffort: reasoningEffort ?? prev.reasoningEffort,
|
||||||
|
tokenUsage: normalizedTokenUsage ?? prev.tokenUsage,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -294,12 +294,12 @@ export const useValidationState = <T extends string>({
|
|||||||
// Track initialization task statuses for the progress UI
|
// Track initialization task statuses for the progress UI
|
||||||
const initializationTasks = {
|
const initializationTasks = {
|
||||||
upcValidation: {
|
upcValidation: {
|
||||||
label: 'Validating UPCs and generating item numbers',
|
label: 'Generating item numbers',
|
||||||
status: upcValidation.initialValidationDone ? 'completed' :
|
status: upcValidation.initialValidationDone ? 'completed' :
|
||||||
hasPendingUpcValidation ? 'in_progress' : 'pending'
|
hasPendingUpcValidation ? 'in_progress' : 'pending'
|
||||||
},
|
},
|
||||||
fieldValidation: {
|
fieldValidation: {
|
||||||
label: 'Validating field requirements and formats',
|
label: 'Checking for field errors',
|
||||||
status: initialValidationComplete ? 'completed' :
|
status: initialValidationComplete ? 'completed' :
|
||||||
isInitialValidationRunning ? 'in_progress' : 'pending'
|
isInitialValidationRunning ? 'in_progress' : 'pending'
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user